Snowy Smile
求最大子矩阵,枚举一个上界,从上往下将同一行的数值丢到线段树里面去维护好最大子段和。一行结束后当前的最大子段和意味着在上界(枚举的)和下界(枚举)确定的情况下,所有子矩阵(左边界为最大子段初始,右边界为结束)中,和最大的那个。那么所有最大子段和最大的那个就是答案。
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cstdlib>
#include<cstring>
#include<cmath>
using namespace std;
typedef long long LL;
const int maxn=4e3+22;
#define sfi(a) scanf("%d",&a)
#define sfl(a) scanf("%lld",&a)
#define sff(a) scanf("%lf",&a)
int n,m;
struct Point
{
int x,y;LL val;
bool operator<(const Point b)const
{
if(y==b.y)return x<b.x;
return y>b.y;
}
}node[maxn];
int hashx[maxn],hashy[maxn];
struct Segmentree
{
LL dat,ldat,rdat,sum;int l,r;
#define l(p) tre[p].l
#define r(p) tre[p].r
#define dat(p) tre[p].dat
#define sum(p) tre[p].sum
#define ldat(p) tre[p].ldat
#define rdat(p) tre[p].rdat
}tre[maxn<<2];
void pushup(int p)
{
sum(p)=sum(p<<1)+sum(p<<1|1);
ldat(p)=max(ldat(p<<1),sum(p<<1)+ldat(p<<1|1));
rdat(p)=max(rdat(p<<1|1),sum(p<<1|1)+rdat(p<<1));
dat(p)=max(rdat(p<<1)+ldat(p<<1|1),max(dat(p<<1|1),dat(p<<1)));
dat(p)=max(dat(p),max(sum(p),max(ldat(p),rdat(p))));
}
void build(int p,int l,int r)
{
l(p)=l;r(p)=r;dat(p)=ldat(p)=rdat(p)=sum(p)=0;
if(l==r){return;}
int mid=(l(p)+r(p))/2;
build(p<<1,l,mid);build(p<<1|1,mid+1,r);
pushup(p);
}
void addtre(int p,int x,LL val)
{
if(l(p)==r(p)&&l(p)==x)
{
sum(p)=sum(p)+val;
dat(p)=ldat(p)=rdat(p)=sum(p);
return;
}
int mid=(l(p)+r(p))/2;
if(x<=mid)addtre(p<<1,x,val);
else addtre(p<<1|1,x,val);
pushup(p);
}
int main()
{
int _;sfi(_);
while(_--)
{
sfi(n);
for(int i=1;i<=n;++i)
{
sfi(node[i].x);sfi(node[i].y);sfl(node[i].val);
hashx[i]=node[i].x;hashy[i]=node[i].y;
}
sort(hashx+1,hashx+1+n);
sort(hashy+1,hashy+1+n);
for(int i=1;i<=n;++i)
{
node[i].x=lower_bound(hashx+1,hashx+1+n,node[i].x)-hashx;
node[i].y=lower_bound(hashy+1,hashy+1+n,node[i].y)-hashy;
}
sort(node+1,node+1+n);
LL ans=-1e18;
for(int i=1;i<=n;++i)
{
if(i!=1&&node[i].y==node[i-1].y)continue;
build(1,1,n);
for(int j=i;j<=n;)
{
int k=j;
while(k<=n&&node[j].y==node[k].y)
{
addtre(1,node[k].x,node[k].val);
k++;
}
j=k;
ans=max(ans,dat(1));
}
}
printf("%lld\n",ans);
}
}