链接
给出2000个点,点的x和y的坐标范围为(-1e9,1e9),可以用一个矩形去包括一些点,求被包括的点的权值和最大是多少。矩形的长宽平行于坐标轴。
一开始看到这个题瞬间就想到了先把点的坐标离散化,然后就是 n 3 n^3 n3的最大子矩阵和的套路,可惜时间复杂不对。一个可行的做法:同样先对点进行离散化,然后利用线段树维护动态子段和,不知道这个的话可以百度学习一下。最后不能像 n 3 n^3 n3的做法那样去枚举上下边,这样复杂度就会更高了,有些点是多出来的无效状态。只需要先对点按照x降序,y降序或者其他的规则去排序,
x=1,y=2
x=2,y=1 | x=2,y=2 | x=2,y=4
x=3,y=4 | x=3,y=8
…
因为都是有序的,很容易就可以判断点在哪一行了,然后只要枚举点即可,复杂度: n 2 l o g ( n ) n^2log(n) n2log(n)
下面的代码方向是从左向右的。
#include
using namespace std;
typedef long long ll;
const int INF=1e9+7;
struct _point{
int x,y;
ll w;
bool operator <(const _point &a)const {
if(y==a.y)return x<a.x;
return y<a.y;
}
}po[2005];
int lsx[2005];
int lsy[2005];
int szx,szy;
template <typename _Tp> inline _Tp read(_Tp&x){
char c11=getchar(),ob=0;x=0;
while(c11^'-'&&!isdigit(c11))c11=getchar();if(c11=='-')c11=getchar(),ob=1;
while(isdigit(c11))x=x*10+c11-'0',c11=getchar();if(ob)x=-x;return x;
}
struct node{
ll sum,ll,lr,lm;
}tree[4005*4];
#define lson rt<<1
#define rson rt<<1|1
void pushup(int rt){
tree[rt].sum=tree[lson].sum+tree[rson].sum;
tree[rt].ll=max(tree[lson].ll,tree[lson].sum+tree[rson].ll);
tree[rt].lr=max(tree[rson].lr,tree[rson].sum+tree[lson].lr);
tree[rt].lm=max(tree[lson].lr+tree[rson].ll,max(tree[lson].lm,tree[rson].lm));
}
void build(int rt,int l,int r){
tree[rt].ll=tree[rt].sum=tree[rt].lr=tree[rt].lm=0;
if(l==r)return;
int mid=(l+r)>>1;
build(lson,l,mid);
build(rson,mid+1,r);
}
void update(int rt,int l,int r,int x,ll k){
if(l==r){
tree[rt].sum+=k;
tree[rt].ll=max(0ll,tree[rt].sum);
tree[rt].lm=max(0ll,tree[rt].sum);
tree[rt].lr=max(0ll,tree[rt].sum);
return ;
}
int mid=(l+r)>>1;
if(x<=mid)update(lson,l,mid,x,k);
else update(rson,mid+1,r,x,k);
pushup(rt);
}
ll query(int rt,int l,int r,int x,int y){
if(x<=l&&r<=y){
return max(tree[rt].lm,max(tree[rt].ll,tree[rt].lr));
}
int mid=(l+r)>>1;
if(y<=mid)return query(lson,l,mid,x,y);
else if(x>mid)return query(rson,mid+1,r,x,y);
else return max(query(lson,l,mid,x,mid),query(rson,mid+1,r,mid+1,y));
}
int main(){
int t;
read(t);
po[0].y=-INF;
for(int ca=1;ca<=t;ca++){
int n;
read(n);
for(int i=1;i<=n;i++){
read(po[i].x),read(po[i].y),read(po[i].w);
lsx[i]=po[i].x;
lsy[i]=po[i].y;
}
sort(lsx+1,lsx+1+n);
sort(lsy+1,lsy+1+n);
szx=unique(lsx+1,lsx+1+n)-lsx-1;
szy=unique(lsy+1,lsy+1+n)-lsy-1;
sort(po+1,po+1+n);
for(int i=1;i<=n;i++){
po[i].x=lower_bound(lsx+1,lsx+1+szx,po[i].x)-lsx;
po[i].y=lower_bound(lsy+1,lsy+1+szy,po[i].y)-lsy;
}
ll ans=0ll;
int l=1;
while(l<=n){
while(po[l].y==po[l-1].y) l++;
build(1,1,szx);
int r=l;
while(r<=n){
update(1,1,szx,po[r].x,po[r].w);
while(r<n&&po[r+1].y==po[r].y){
r++;update(1,1,szx,po[r].x,po[r].w);
}
ans=max(ans,query(1,1,szx,1,szx));
r++;
}
l++;
}
printf("%lld\n",ans);
}
return 0;
}