Snowy Smile
Problem Description
There are n pirate chests buried in Byteland, labeled by 1,2,…,n.1,2,…,n.1,2,…,n. The iii-th chest’s location is (xi,yi)(x_i,y_i)(xi,yi), and its value is wi,wiw_i, w_iwi,wi can be negative since the pirate can add some poisonous gases into the chest. When you open the iii-th pirate chest, you will get wiw_iwi value.
You want to make money from these pirate chests. You can select a rectangle, the sides of which are all paralleled to the axes, and then all the chests inside it or on its border will be opened. Note that you must open all the chests within that range regardless of their values are positive or negative. But you can choose a rectangle with nothing in it to get a zero sum.
Please write a program to find the best rectangle with maximum total value.
Input
The first line of the input contains an integer T(1≤T≤100)T(1\leq T\leq 100)T(1≤T≤100), denoting the number of test cases.
In each test case, there is one integer n(1≤n≤2000)n(1\leq n\leq 2000)n(1≤n≤2000) in the first line, denoting the number of pirate chests.
For the next n lines, each line contains three integers xi,yi,wi(−109≤xi,yi,wi≤109)x_i,y_i,w_i(−10^9\leq x_i,y_i,w_i\leq 10^9)xi,yi,wi(−109≤xi,yi,wi≤109), denoting each pirate chest.
It is guaranteed that ∑n≤10000\sum n\leq 10000∑n≤10000.
Output
For each test case, print a single line containing an integer, denoting the maximum total value.
Sample Input
2
4
1 1 50
2 1 50
1 2 50
2 2 -500
2
-1 1 5
-1 1 1
Sample Output
100
6
Source
2019 Multi-University Training Contest 6
题意
- 就是有一个矩阵,这个矩阵中只有200020002000个点有值,其他位置值为0,让你求最大子矩阵和【矩阵大小可以为0】
题解
- 其实之前牛客多校也出过一个类似的题,处理方法都很套路,就是枚举宽度然后要很快的找最长的那个矩阵,记得上次牛客是枚举宽度+单调队列处理,而这题,对于宽度为[l,r+1][l,r+1][l,r+1]的矩形,其实它的信息可以在宽度为[l,r][l,r][l,r]的子矩形的基础上多加上第r+1r+1r+1行的信息,这个信息就是每一列的和,然后怎么快速知道最大子矩阵呢?还记得线段树入门题目最大子矩阵和吗?只用线段树维护最大前缀,后缀,区间最值,区间和就行了,pushuppushuppushup操作很简单可以参考代码
- 签到速度不够,题目刷的太少,学过的东西不知道用!!!
#include<bits/stdc++.h>
using namespace std;
const int maxn=2005;
#define inf 0x3f3f3f3f3f3f3f3f
struct node{
long long pre,suf,sum,maxx;
node(long long a=0,long long b=0,long long c=0,long long d=0) {
pre=a;suf=b;sum=c;maxx=d;
}
}tree[maxn<<2];
struct point{
int x,y;long long val;
point(int a=0,int b=0) {
x=a;y=b;
}
}p[maxn];
void pushup(int id)
{
tree[id].pre=max(tree[id<<1].pre,tree[id<<1].sum+tree[id<<1|1].pre);
tree[id].suf=max(tree[id<<1|1].suf,tree[id<<1|1].sum+tree[id<<1].suf);
tree[id].maxx=max(tree[id<<1].maxx,max(tree[id<<1|1].maxx,tree[id<<1].suf+tree[id<<1|1].pre));
tree[id].sum=(tree[id<<1].sum+tree[id<<1|1].sum);
}
void build(int id,int l,int r)
{
tree[id]=node(0,0,0,0);
if(l==r) return;
int mid=(l+r)>>1;
build(id<<1,l,mid);
build(id<<1|1,mid+1,r);
}
void update(int id,int L,int R,int pos,long long val)
{
if(L==R) {
tree[id].sum+=val;
tree[id].pre+=val;
tree[id].suf+=val;
tree[id].maxx+=val;
return;
}
int mid=(L+R)>>1;
if(pos<=mid) {
update(id<<1,L,mid,pos,val);
}else {
update(id<<1|1,mid+1,R,pos,val);
}
pushup(id);
}
int n,c[maxn],d[maxn];
vector<point> vec[maxn];
int main()
{
int t;scanf("%d",&t);
while(t--) {
scanf("%d",&n);
for(int i=1;i<=n;i++) {
scanf("%d %d %lld",&p[i].x,&p[i].y,&p[i].val);
c[i]=p[i].x;
d[i]=p[i].y;
}
sort(c+1,c+n+1);sort(d+1,d+n+1);
int tot1=unique(c+1,c+n+1)-c-1,tot2=unique(d+1,d+n+1)-d-1;
for(int i=1;i<=n;i++) {
p[i].x=lower_bound(c+1,c+tot1+1,p[i].x)-c;
p[i].y=lower_bound(d+1,d+tot2+1,p[i].y)-d;
vec[p[i].x].push_back(p[i]);
}
long long ans=0;
for(int i=1;i<=tot1;i++) {
build(1,1,tot2);
for(int j=i;j<=tot1;j++) {
for(auto p1:vec[j]) {
update(1,1,tot2,p1.y,p1.val);
}
ans=max(ans,tree[1].maxx);
}
}
printf("%lld\n",ans);
for(int i=1;i<=tot1;i++) vec[i].clear();
}
}