zoukankan      html  css  js  c++  java
  • HDU6638 Snowy Smile (线段树+二维最大子段和)

    2019杭电多校第六场的一道签到题

    这次我们显然要求的二维矩阵的最大值,分析题目我们可以得到几个细节。

    1.首先数据很大,肯定要离散化。

    2.离散化后,我们想象有很多点在一个平面内,要统计矩阵最大值

    3.我们之前接触过如何求一条线上的最大子段和,只要用线段树维护四个值就能够解决

    4.根据已知,我们发现求矩阵和也是可以这么做的,因为他是一个矩形,所以我们假如我们有两行,其实可以把第二行的对应数据加到第一行上去,进行压维操作,再求一维的最大子段和。

    5.我们要考虑所有的情况,因此我们以x轴作为线段树的区间,之后来枚举y轴,就可以把所有情况枚举出来。

    6.这题爆int,并且我们可以不框住任何矩形,所以最小值肯定是0

    #include<iostream>
    #include<algorithm>
    #include<cstring>
    #include<cstdio>
    #include<vector> 
    using namespace std;
    typedef long long ll;
    const int N=1e5+10;
    const int inf=0x3f3f3f3f;
    vector<int> xi;
    vector<int> yi;
    struct node{
        int l,r;
        ll sum;
        ll tsum;
        ll lsum;
        ll rsum;
    }tr[N<<2];
    struct qi{
        int x,y;
        ll w;
    }q[N];
    bool cmp(qi a,qi b){
        if(a.y==b.y)
        return a.x<b.x;
        return a.y<b.y; 
    }
    void build(int u,int l,int r){
        if(l==r){
            tr[u]={l,l};
        }
        else{
            tr[u]={l,r};
            int mid=l+r>>1;
            build(u<<1,l,mid);
            build(u<<1|1,mid+1,r);
        }
    }
    int findy(int x){
        return lower_bound(yi.begin(),yi.end(),x)-yi.begin()+1;
    }
    int findx(int x){
        return lower_bound(xi.begin(),xi.end(),x)-xi.begin()+1;
    }
    void pushup(int u){
        tr[u].lsum=max(tr[u<<1].lsum,tr[u<<1].sum+tr[u<<1|1].lsum);
        tr[u].rsum=max(tr[u<<1|1].rsum,tr[u<<1|1].sum+tr[u<<1].rsum);
        tr[u].tsum=max(max(tr[u<<1].tsum,tr[u<<1|1].tsum),tr[u<<1].rsum+tr[u<<1|1].lsum);
        tr[u].sum=tr[u<<1].sum+tr[u<<1|1].sum;
    }
    void modify(int u,int w,ll x){
        if(tr[u].l==tr[u].r){
            tr[u].lsum=tr[u].sum=tr[u].rsum=tr[u].tsum=tr[u].sum+x;
            return ;
        }
        else{
            int mid=tr[u].l+tr[u].r>>1;
            if(w<=mid)
            modify(u<<1,w,x);
            else
            modify(u<<1|1,w,x);
            pushup(u);
        }
    }
    int main(){
        int t;
        cin>>t;
        while(t--){
            int n;
            int i;
            cin>>n;
            xi.clear();
            yi.clear();
            for(i=1;i<=n;i++){
                scanf("%d%d%lld",&q[i].x,&q[i].y,&q[i].w);
                xi.push_back(q[i].x);
                yi.push_back(q[i].y);
            }
            sort(q+1,q+n+1,cmp);
            sort(xi.begin(),xi.end());
            xi.erase(unique(xi.begin(),xi.end()),xi.end());
            sort(yi.begin(),yi.end());
            yi.erase(unique(yi.begin(),yi.end()),yi.end());
            int nx=xi.size();
            int ny=yi.size();
            int now=1;
            int k;
            ll ans=0;
            for(i=1;i<=ny;i++){  //枚举下边界 
                build(1,1,nx);
                for(int j=i,k=now;j<=ny;j++){ //上边界                 
                
                    while(k<=n&&findy(q[k].y)==j){
                        modify(1,findx(q[k].x),q[k].w);
                        k++;
                    }        
                    if(j==i)
                    now=k;
                    ans=max(ans,tr[1].tsum);
    
                }
            }
            cout<<ans<<endl;
        }
    }
    View Code
  • 相关阅读:
    java JDBC DAO ORM Domain
    《硅谷钢铁侠-- 埃隆·马斯克的冒险人生》
    在启动MYSQL时出现问题:“ERROR 2003 (HY000): Can't connect to MySQL server on 'localhost' (10061)”
    使用IntelliJ IDEA开发java web
    [django]用日期来查询datetime类型字段
    2020/5/31
    图解排序算法(三)之堆排序
    图解排序算法(二)之希尔排序
    图解排序算法(一)之3种简单排序(选择,冒泡,直接插入)
    Oracle约束(Constraint)详解
  • 原文地址:https://www.cnblogs.com/ctyakwf/p/12310912.html
Copyright © 2011-2022 走看看