HDU 6638 Snowy Smile

题意:平面有\(n\)个有权值的点,求最大子矩阵和


离散化后按横坐标升序排序,\(n^2\)枚举矩阵左右边界,设\(v[i]\)表示在左右边界内所有纵坐标为\(i\)的点的权值和,求最大子段和即可,用线段树维护带修改的区间最大子段和

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int maxn=2010;
#define ls (node<<1)
#define rs (node<<1|1)
int n;
struct s
{
    int x,y,z;
}p[maxn];
int hx[maxn],hy[maxn];

struct Segtree
{
    ll max,vl,vr,sum;
}Tree[maxn<<2];
void updata(int node)
{
    Tree[node].max=max(Tree[ls].max,max(Tree[rs].max,Tree[ls].vr+Tree[rs].vl));
    Tree[node].sum=Tree[ls].sum+Tree[rs].sum;
    Tree[node].vl=max(Tree[ls].vl,Tree[ls].sum+Tree[rs].vl);
    Tree[node].vr=max(Tree[rs].vr,Tree[rs].sum+Tree[ls].vr);
}
void add(int l,int r,int node,int ps,int to)
{
    if(l==r)
    {
        Tree[node].sum+=to;
        Tree[node].max+=to;
        Tree[node].vl+=to;
        Tree[node].vr+=to;
        return ;
    }
    int mid=(l+r)>>1;
    if(ps<=mid)
        add(l,mid,ls,ps,to);
    else
        add(mid+1,r,rs,ps,to);
    updata(node);
}
void clr(int l,int r,int node)
{
    Tree[node].max=Tree[node].vl=Tree[node].vr=Tree[node].sum=0;
    if(l==r)return ;
    int mid=(l+r)>>1;
    clr(l,mid,ls);
    clr(mid+1,r,rs);
}

bool cmp(s a, s b)
{
    return a.x<b.x;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        scanf("%d",&n);
        int tot=0;
        for(int i=0;i<n;i++)
        {
            scanf("%d%d%d",&p[i].x,&p[i].y,&p[i].z);
            hx[i]=p[i].x;
            hy[i]=p[i].y;
        }
    
        sort(hx,hx+n);
        sort(hy,hy+n);
        int nx=unique(hx,hx+n)-hx;
        int ny=unique(hy,hy+n)-hy;
        for(int i=0;i<n;i++)
        {
            p[i].x=lower_bound(hx,hx+nx,p[i].x)-hx+1;
            p[i].y=lower_bound(hy,hy+ny,p[i].y)-hy+1;
        }

        sort(p,p+n,cmp);
        int pos=0,now=0;
        ll ans=0;
        for(int i=1;i<=nx;i++)
        {
            clr(1,ny,1);
            for(int j=i,pos=now;j<=nx;j++)
            {
                while(pos<n&&p[pos].x==j)
                {
                    add(1,ny,1,p[pos].y,p[pos].z);
                    pos++;
                }
                if(j==i)now=pos;
                ans=max(ans,Tree[1].max);
            }
        }
        printf("%lld\n",ans);
    }
    return 0;
}
posted @ 2020-06-26 21:39  Zeronera  阅读(100)  评论(0)    收藏  举报