zoukankan      html  css  js  c++  java
  • HDU多校第六场——HDU6638 Snowy Smile(线段树区间合并)

    题意:有n个点(n<=2000),每个点都有价值,求一个矩形内所有点价值和的最大值是多少

    一维的静态最大子段和用dp在O(n)时间内解决,带修改查询区间最大子段和可以用线段树区间合并O(nlogn)写

    二维的最大子矩阵和可以通过压行再dpO(n^3)写。

    这题对坐标离散化一下就转化为求最大子矩阵和的问题了,然后n^3肯定是不行的,然后利用离散后是2000*2000的图上有2000个点,矩阵很稀疏这个性质,可以通过枚举起始行s,终点行e,用然后用线段树维护s~e行,每列的信息,转化为一维最大子段和来算。每次枚举起始行时都要重新建树,然后枚举终点行时,都把这行的信息更新到线段树里去,复杂度是n(nlogn(建树)+nlogn(更新)),这题关键是有效点很少只有n个,如果是n^2个就没了。

    #include<bits/stdc++.h>
    using namespace std;
    #define ls rt<<1
    #define rs (rt<<1)+1
    #define ll long long
    #define fuck(x) cout<<#x<<"     "<<x<<endl;
    typedef pair<int,int>pii;
    const ll inf=9e18;
    const int maxn=2000+10;
    int d[4][2]={1,0,-1,0,0,1,0,-1};
    vector<pii>row[maxn];
    struct node{
        int x,y,w;
    }p[maxn];
    int lshx[maxn],lshy[maxn],cnt1,cnt2;
    ll maxx[maxn<<2],lmaxx[maxn<<2],rmaxx[maxn<<2],sum[maxn<<2];
    void pushup(int rt)
    {
        sum[rt]=sum[ls]+sum[rs];
        lmaxx[rt]=max(lmaxx[ls],sum[ls]+lmaxx[rs]);
        rmaxx[rt]=max(rmaxx[rs],sum[rs]+rmaxx[ls]);
        maxx[rt]=max(maxx[ls],maxx[rs]);
        maxx[rt]=max(maxx[rt],rmaxx[ls]+lmaxx[rs]);
    }
    void update(int rt,int L,int R,int pos,int val){
        if(L==R)
        {
            sum[rt]+=val;
            maxx[rt]=lmaxx[rt]=rmaxx[rt]=max(0LL,sum[rt]);
            return ;
        }
        int mid=(L+R)>>1;
        if(pos<=mid)
            update(ls,L,mid,pos,val);
        else
            update(rs,mid+1,R,pos,val);
        pushup(rt);
    }
    int main(){
        int t,n;
        ll ans;
        scanf("%d",&t);
        while(t--)
        {
            ans=-inf;
            cnt1=cnt2=0;
            scanf("%d",&n);
            for(int i=1;i<=n;i++) row[i].clear();
            for(int i=1;i<=n;i++) scanf("%d%d%d",&(p[i].x),&(p[i].y),&(p[i].w)),lshx[++cnt1]=p[i].x,lshy[++cnt2]=p[i].y;
            sort(lshx+1,lshx+cnt1+1);
            sort(lshy+1,lshy+cnt2+1);
            cnt1=unique(lshx+1,lshx+cnt1+1)-lshx-1;
            cnt2=unique(lshy+1,lshy+cnt2+1)-lshy-1;
            for(int i=1;i<=n;i++)
            {
                int tmpx,tmpy;
                tmpx=lower_bound(lshx+1,lshx+cnt1+1,p[i].x)-lshx;
                tmpy=lower_bound(lshy+1,lshy+cnt2+1,p[i].y)-lshy;
                row[tmpx].push_back(make_pair(tmpy,p[i].w));
            }
            for(int i=1;i<=cnt1;i++)
            {
                for(int j=1;j<=cnt2*4;j++)
                    maxx[j]=lmaxx[j]=rmaxx[j]=sum[j]=0;
                for(int j=i;j<=cnt1;j++)
                {
                    for(int k=0;k<row[j].size();k++)
                        update(1,1,cnt2,row[j][k].first,row[j][k].second);
                    ans=max(ans,maxx[1]);
                }
            }
            printf("%lld
    ",ans);
        }
        return 0;
    }
  • 相关阅读:
    搬运好文章->>>>>子网划分详解
    搬运好文章->>>>>子网掩码详解
    搬运好文章->>>>>IP地址和MAC地址详解
    搬运好文章->>>>>计算机中进制之间的关系和转换
    extend 与 append 的区别
    数据类型---字符串
    多引号的作用,字符串格式化
    列表复制的几种方法
    十六进制和二进制转换
    python奇偶数求和
  • 原文地址:https://www.cnblogs.com/eason9906/p/11754717.html
Copyright © 2011-2022 走看看