题意
给n个带权点,求最大子矩阵和
做法
没想到n^2log的做法,老年选手预兆
考虑离散,枚举矩形的下边界,然后一行一行加入点,用线段树维护最大子段和
每加入一整行我们就在线段树中查询、更新答案
我的代码常数特别大,但是能过,这就很奇妙。。
代码
#include <stdio.h>
#include <string.h>
#include <algorithm>
#include <vector>
#define rep(i,st,ed) for (register int i=st;i<=ed;++i)
#define max(x,y) ((x)>(y)?(x):(y))
typedef long long LL;
const int N=5005;
const int INF=(1e9)+7;
struct pos {int x,y,w;} p[N];
std:: vector <int> vec[N];
LL ls[N<<2],rs[N<<2],mx[N<<2],s[N<<2];
int sx[N],sy[N];
int read() {
int x=0,v=1; char ch=getchar();
for (;ch<'0'||ch>'9';v=(ch=='-')?(-1):v,ch=getchar());
for (;ch<='9'&&ch>='0';x=x*10+ch-'0',ch=getchar());
return x*v;
}
void pushUp(int now) {
s[now]=s[now<<1]+s[now<<1|1];
ls[now]=max(ls[now<<1],s[now<<1]+ls[now<<1|1]);
rs[now]=max(rs[now<<1|1],s[now<<1|1]+rs[now<<1]);
mx[now]=max(max(mx[now<<1|1],mx[now<<1]),rs[now<<1]+ls[now<<1|1]);
}
void modify(int now,int tl,int tr,int x,int v) {
if (tl==tr) {
s[now]+=v,mx[now]+=v;
ls[now]+=v,rs[now]+=v;
return ;
}
int mid=(tl+tr)>>1;
if (x<=mid) modify(now<<1,tl,mid,x,v);
else modify(now<<1|1,mid+1,tr,x,v);
pushUp(now);
}
void build(int now,int tl,int tr) {
mx[now]=s[now]=ls[now]=rs[now]=0;
if (tl==tr) return ;
int mid=(tl+tr)>>1;
build(now<<1,tl,mid); build(now<<1|1,mid+1,tr);
}
bool cmp(pos a,pos b) {
return (a.x!=b.x)?(a.x<b.x):(a.y<b.y);
}
int main(void) {
freopen("data.in","r",stdin);
freopen("myp.out","w",stdout);
for (int T=read();T--;) {
int n=read();
rep(i,1,n) {
p[i].x=read(),p[i].y=read();
sx[i]=p[i].x,sy[i]=p[i].y;
p[i].w=read();
}
std:: sort(sx+1,sx+n+1);
std:: sort(sy+1,sy+n+1);
int tx=std:: unique(sx+1,sx+n+1)-sx-1;
int ty=std:: unique(sy+1,sy+n+1)-sy-1;
rep(i,1,n) {
p[i].x=std:: lower_bound(sx+1,sx+tx+1,p[i].x)-sx;
p[i].y=std:: lower_bound(sy+1,sy+ty+1,p[i].y)-sy;
}
// std:: sort(p+1,p+n+1,cmp);
rep(i,1,tx) vec[i].clear();
rep(i,1,n) vec[p[i].x].push_back(i);
LL ans=0;
rep(i,1,tx) {
build(1,1,ty);
rep(j,i,tx) {
for (int k=0,size=vec[j].size();k<size;++k) {
int tmp=vec[j][k];
modify(1,1,ty,p[tmp].y,p[tmp].w);
}
(mx[1]>ans)?(ans=mx[1]):0;
}
}
printf("%lld\n", ans);
}
return 0;
}