zoukankan      html  css  js  c++  java
  • 2019牛客暑期多校训练营(第一场)I Points Division(dp+线段树优化)

    给你n个点,第i个点在的位置为(xi,yi),有两个属性值(ai,bi)。现在让你把这n个点划分为A和B两个部分,使得最后不存在i∈A和j∈B,使得xi>=xj且yi<=yj。然后对于所有的划分方法,找到并输出最大和

    现在的疑问点在于为什么要多加一个高度为0的虚拟节点(因为要考虑全是A集合的)

    #include <bits/stdc++.h>
    #define ll long long
    #define inf 0x3f3f3f3f
    using namespace std;
    const int N = 1e5+7;
    const double eps = 1e-8;
    const ll mod = 1e9+7;
    struct Point{
        int x,y;
        ll a,b;
        friend bool operator < (Point a,Point b){
            if(a.x==b.x) return a.y>b.y;
            return a.x<b.x;
        }
    };
    Point p[N];
    ll h[N];
    struct tree{
        int l,r;
        ll lazy,v;
    };
    tree t[N<<2];
    void build(int p,int l,int r){
        t[p]=(tree){l,r,0,0};
        if(l==r) return ;
        int mid=(l+r)>>1;
        build(p<<1,l,mid);
        build(p<<1|1,mid+1,r);
    }
    void pushdown(int p){
        if(t[p].lazy){
            t[p<<1].v+=t[p].lazy;
            t[p<<1|1].v+=t[p].lazy;
            t[p<<1].lazy+=t[p].lazy;
            t[p<<1|1].lazy+=t[p].lazy;
            t[p].lazy=0;
        }
    }
    void update(int p,int pos,ll x){
        if(t[p].l==t[p].r&&t[p].l==pos){
            t[p].v=max(t[p].v,x);
            return ;
        }
        pushdown(p);
        int mid=(t[p].l+t[p].r)>>1;
        if(pos<=mid) update(p<<1,pos,x);
        else update(p<<1|1,pos,x);
        t[p].v=max(t[p<<1].v,t[p<<1|1].v);
    }
    void update1(int p,int l,int r,ll x){
        if(l>r) return ;
        if(l<=t[p].l&&t[p].r<=r){
            t[p].v+=x;
            t[p].lazy+=x;
            return ;
        }
        pushdown(p);
        int mid=(t[p].l+t[p].r)>>1;
        if(l<=mid) update1(p<<1,l,r,x);
        if(mid<r) update1(p<<1|1,l,r,x);
        t[p].v=max(t[p<<1].v,t[p<<1|1].v);
    }
    ll query(int p,int l,int r){
        if(l>r) return 0;
        if(l<=t[p].l&&t[p].r<=r){
            return t[p].v;
        }
        int mid=(t[p].l+t[p].r)>>1;
        pushdown(p);
        ll res=0;
        if(l<=mid) res=max(res,query(p<<1,l,r));
        if(mid<r) res=max(res,query(p<<1|1,l,r));
        return res;
    }
    int main(){
        ios::sync_with_stdio(false);
        cin.tie(0); cout.tie(0);
        int n;
        while(cin>>n){
            int cnt=0;
            for(int i=1;i<=n;i++){
                cin>>p[i].x>>p[i].y>>p[i].a>>p[i].b;
                h[++cnt]=p[i].y;
            }
            sort(p+1,p+1+n);
            sort(h+1,h+1+cnt);
            cnt=unique(h+1,h+1+cnt)-(h+1);
            for(int i=1;i<=n;i++) p[i].y=lower_bound(h+1,h+1+cnt,p[i].y)-h+1;
            cnt++;
            build(1,1,cnt);
            for(int i=1;i<=n;i++){
                ll res=query(1,1,p[i].y);
                update(1,p[i].y,res+p[i].b);
                update1(1,p[i].y+1,cnt,p[i].b);
                update1(1,1,p[i].y-1,p[i].a);
            }
            cout<<t[1].v<<endl;
        }
        return 0;
    }

     

  • 相关阅读:
    软件工程 实验二 结对编程(第一阶段)
    C#中的线程(一)入门
    C# Using与Try..Finally 语句探究
    中兴一面归来
    Log4Net 入门示例
    C++ 临时对象
    C宏定义探析
    MFC 对话框 快捷键设置(alt+s)
    C#中的线程(二) 线程同步基础
    Ip地址的正则表达式
  • 原文地址:https://www.cnblogs.com/wmj6/p/11216324.html
Copyright © 2011-2022 走看看