Codeforces 1221 F Choose a Square —— 线段树,前缀和

This way

题意:

二维平面上有n个点,每个点上有权值,你可以选择一个矩形区域,使得这个矩形包括的点的权值和-矩形边长的值最大。矩形的右上角和左下角必须在x=y这条直线上。

题解:

一开始想的是dp,发现好像不行,然后一看这个左下右上的条件就知道是线段树了,首先离散化,然后枚举右上角,对于新增的点,用前缀和的方式增加到线段树上,然后增加的边长也用前缀和的方式增加到线段树上,最后查询最大值即可。

#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define pa pair<int,ll>
const int N=1e6+5;
vector<pa>vec[N];
ll mx[N*4],f[N*4],c[N];
int x[N],y[N],b[N];
void push_down(int root){
    if(!f[root])
        return ;
    mx[root<<1]+=f[root];
    mx[root<<1|1]+=f[root];
    f[root<<1]+=f[root];
    f[root<<1|1]+=f[root];
    f[root]=0;
}
void update(int l,int r,int root,int ql,int qr,ll v){
    if(l>=ql&&r<=qr){
        mx[root]+=v;
        f[root]+=v;
        return ;
    }
    push_down(root);
    int mid=l+r>>1;
    if(mid>=ql)
        update(l,mid,root<<1,ql,qr,v);
    if(mid<qr)
        update(mid+1,r,root<<1|1,ql,qr,v);
    mx[root]=max(mx[root<<1],mx[root<<1|1]);
}
int p;
ll query(int l,int r,int root,int ql,int qr){
    if(l==r){
        p=l;
        return mx[root];
    }
    push_down(root);
    int mid=l+r>>1;
    if(mid>=ql&&mid<qr){
        if(mx[root<<1]<mx[root<<1|1])
            return query(mid+1,r,root<<1|1,ql,qr);
        else
            return query(l,mid,root<<1,ql,qr);
    }
    else if(mid>=ql)
        return query(l,mid,root<<1,ql,qr);
    else
        return query(mid+1,r,root<<1|1,ql,qr);
}
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d%d%lld",&x[i],&y[i],&c[i]),b[i*2-1]=x[i],b[i*2]=y[i];
    sort(b+1,b+1+n*2);
    int all=unique(b+1,b+1+n*2)-b-1;
    int x1=2e9,y1=2e9,x2=2e9,y2=2e9;
    ll ans=0;
    for(int i=1;i<=n;i++){
        x[i]=lower_bound(b+1,b+1+all,x[i])-b;
        y[i]=lower_bound(b+1,b+1+all,y[i])-b;
        if(y[i]<x[i])
            vec[x[i]].push_back({y[i],c[i]});
        else
            vec[y[i]].push_back({x[i],c[i]});
    }
    for(int i=1;i<=all;i++){
        if(i>1)
            update(1,all,1,1,i-1,b[i-1]-b[i]);
        for(auto j:vec[i])
            update(1,all,1,1,j.first,j.second);
        ll v=query(1,all,1,1,i);
        if(v>ans)
            ans=v,x1=y1=b[p],x2=y2=b[i];
    }
    printf("%lld\n",ans);
    printf("%d %d %d %d\n",x1,y1,x2,y2);
    return 0;
}

发布了554 篇原创文章 · 获赞 31 · 访问量 5万+

猜你喜欢

转载自blog.csdn.net/tianyizhicheng/article/details/104294876