「2019牛客多校第一场I」Points Division【线段树+dp】

16 篇文章 0 订阅
题目链接:https://ac.nowcoder.com/acm/contest/881/I

题面

在这里插入图片描述

题解

  • 很妙的线段树维护 d p dp dp的题
  • 首先需要明确的是需要怎样将其划分为两个满足条件的集合,根据题意,可以知道可以用一个台阶将集合划分,如图
    在这里插入图片描述
  • 然后就可以将每个点的 y y y进行离散化,然后考虑将这些点优先按照 x x x升序,然后 y y y升序的规则排序,显然每经过一个点,它所带来的贡献需要修改的是一个区间,所以考虑线段树维护区间最大值,然后进行状态转移
  • 转移的过程很妙,代码语言能更好说明~~~
#include<bits/stdc++.h>
using namespace std;

namespace IO{ 
    #define BUF_SIZE 100000 
    #define OUT_SIZE 100000 
    #define ll long long 
    //fread->read 

    bool IOerror=0; 
    inline char nc(){ 
        static char buf[BUF_SIZE],*p1=buf+BUF_SIZE,*pend=buf+BUF_SIZE; 
        if (p1==pend){ 
            p1=buf; pend=buf+fread(buf,1,BUF_SIZE,stdin); 
            if (pend==p1){IOerror=1;return -1;} 
            //{printf("IO error!\n");system("pause");for (;;);exit(0);} 
        } 
        return *p1++; 
    } 
    inline bool blank(char ch){return ch==' '||ch=='\n'||ch=='\r'||ch=='\t';} 
    inline bool read(int &x){ 
        bool sign=0; char ch=nc(); x=0; 
        for (;blank(ch);ch=nc()); 
        if (IOerror)return false; 
        if (ch=='-')sign=1,ch=nc(); 
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; 
        if (sign)x=-x; return true;
    } 
    inline void read(ll &x){ 
        bool sign=0; char ch=nc(); x=0; 
        for (;blank(ch);ch=nc()); 
        if (IOerror)return; 
        if (ch=='-')sign=1,ch=nc(); 
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; 
        if (sign)x=-x; 
    } 
    inline void read(double &x){ 
        bool sign=0; char ch=nc(); x=0; 
        for (;blank(ch);ch=nc()); 
        if (IOerror)return; 
        if (ch=='-')sign=1,ch=nc(); 
        for (;ch>='0'&&ch<='9';ch=nc())x=x*10+ch-'0'; 
        if (ch=='.'){ 
            double tmp=1; ch=nc(); 
            for (;ch>='0'&&ch<='9';ch=nc())tmp/=10.0,x+=tmp*(ch-'0'); 
        } 
        if (sign)x=-x; 
    } 
    inline void read(char *s){ 
        char ch=nc(); 
        for (;blank(ch);ch=nc()); 
        if (IOerror)return; 
        for (;!blank(ch)&&!IOerror;ch=nc())*s++=ch; 
        *s=0; 
    } 
    inline void read(char &c){ 
        for (c=nc();blank(c);c=nc()); 
        if (IOerror){c=-1;return;} 
    } 
    //fwrite->write 
    struct Ostream_fwrite{ 
        char *buf,*p1,*pend; 
        Ostream_fwrite(){buf=new char[BUF_SIZE];p1=buf;pend=buf+BUF_SIZE;} 
        void out(char ch){ 
            if (p1==pend){ 
                fwrite(buf,1,BUF_SIZE,stdout);p1=buf; 
            } 
            *p1++=ch; 
        } 
        void print(int x){ 
            static char s[15],*s1;s1=s; 
            if (!x)*s1++='0';if (x<0)out('-'),x=-x; 
            while(x)*s1++=x%10+'0',x/=10; 
            while(s1--!=s)out(*s1); 
        } 
        void println(int x){ 
            static char s[15],*s1;s1=s; 
            if (!x)*s1++='0';if (x<0)out('-'),x=-x; 
            while(x)*s1++=x%10+'0',x/=10; 
            while(s1--!=s)out(*s1); out('\n'); 
        } 
        void print(ll x){ 
            static char s[25],*s1;s1=s; 
            if (!x)*s1++='0';if (x<0)out('-'),x=-x; 
            while(x)*s1++=x%10+'0',x/=10; 
            while(s1--!=s)out(*s1); 
        } 
        void println(ll x){ 
            static char s[25],*s1;s1=s; 
            if (!x)*s1++='0';if (x<0)out('-'),x=-x; 
            while(x)*s1++=x%10+'0',x/=10; 
            while(s1--!=s)out(*s1); out('\n'); 
        } 
        void print(double x,int y){ 
            static ll mul[]={1,10,100,1000,10000,100000,1000000,10000000,100000000, 
                1000000000,10000000000LL,100000000000LL,1000000000000LL,10000000000000LL, 
                100000000000000LL,1000000000000000LL,10000000000000000LL,100000000000000000LL}; 
            if (x<-1e-12)out('-'),x=-x;x*=mul[y]; 
            ll x1=(ll)floor(x); if (x-floor(x)>=0.5)++x1; 
            ll x2=x1/mul[y],x3=x1-x2*mul[y]; print(x2); 
            if (y>0){out('.'); for (size_t i=1;i<y&&x3*mul[i]<mul[y];out('0'),++i) {}; print(x3);} 
        } 
        void println(double x,int y){print(x,y);out('\n');} 
        void print(char *s){while (*s)out(*s++);} 
        void println(char *s){while (*s)out(*s++);out('\n');} 
        void flush(){if (p1!=buf){fwrite(buf,1,p1-buf,stdout);p1=buf;}} 
        ~Ostream_fwrite(){flush();} 
    }Ostream; 
    inline void print(int x){Ostream.print(x);} 
    inline void println(int x){Ostream.println(x);} 
    inline void print(char x){Ostream.out(x);} 
    inline void println(char x){Ostream.out(x);Ostream.out('\n');} 
    inline void print(ll x){Ostream.print(x);} 
    inline void println(ll x){Ostream.println(x);} 
    inline void print(double x,int y){Ostream.print(x,y);} 
    inline void println(double x,int y){Ostream.println(x,y);} 
    inline void print(char *s){Ostream.print(s);} 
    inline void println(char *s){Ostream.println(s);} 
    inline void println(){Ostream.out('\n');} 
    inline void flush(){Ostream.flush();}
    #undef ll 
    #undef OUT_SIZE 
    #undef BUF_SIZE 
};
using namespace IO;

const int maxn=1e5+10;
struct node{
    int l,r;
    long long mark,maxx;
    node(int a=0,int b=0,long long c=0,long long d=0) {
        l=a;r=b;mark=c;maxx=d;
    }
}tree[maxn<<2];

void build(int id,int le,int ri)
{
    tree[id]=node(le,ri,0,0);
    if(le==ri) return; 
    int mid=(le+ri)>>1;
    build(id<<1,le,mid);build(id<<1|1,mid+1,ri);
}

void pushup(int id) 
{
    tree[id].maxx=max(tree[id<<1].maxx,tree[id<<1|1].maxx);
}

void down(int id)
{
    tree[id<<1].maxx+=tree[id].mark;
    tree[id<<1|1].maxx+=tree[id].mark;
    tree[id<<1].mark+=tree[id].mark;
    tree[id<<1|1].mark+=tree[id].mark;
    tree[id].mark=0;
}

void change(int id,int pos,long long val) //单点更新
{
    if(tree[id].l==tree[id].r) {tree[id].maxx=val;return;}
    if(tree[id].mark) down(id);
    int mid=(tree[id].l+tree[id].r)>>1;
    if(pos<=mid) change(id<<1,pos,val);
    else change(id<<1|1,pos,val);
    pushup(id);
}

void update(int id,int le,int ri,int add)
{
    if(tree[id].l>=le&&tree[id].r<=ri) {
        tree[id].mark+=add;
        tree[id].maxx+=add;
        return;
    }
    if(tree[id].mark) down(id);
    int mid=(tree[id].l+tree[id].r)>>1;
    if(le>mid) update(id<<1|1,le,ri,add);
    else if(ri<=mid) update(id<<1,le,ri,add);
    else update(id<<1,le,mid,add),update(id<<1|1,mid+1,ri,add);

    pushup(id);

}

long long query(int id,int le,int ri)
{
    long long res=0;
    if(tree[id].l>=le&&tree[id].r<=ri) return tree[id].maxx;
    if(tree[id].mark) down(id);
    int mid=(tree[id].l+tree[id].r)>>1;
    if(le>mid) res=max(res,query(id<<1|1,le,ri));
    else if(ri<=mid) res=max(res,query(id<<1,le,ri));
    else res=max(res,max(query(id<<1,le,mid),query(id<<1|1,mid+1,ri)));
    pushup(id);return res;
}

struct point{
    int x,y;long long a,b;
    point(int c=0,int d=0,long long e=0,long long f=0){
        x=c;y=d;a=e;b=f;
    }
    friend bool operator<(const point &a,const point &b){
        return a.x==b.x?a.y>b.y:a.x<b.x;
    }
}p[maxn];

int n;long long h[maxn];

int main()
{
    while(read(n)) {
        for(int i=1;i<=n;i++) read(p[i].x),read(p[i].y),read(p[i].a),read(p[i].b),h[i]=p[i].y;
        h[n+1]=0;sort(h+1,h+n+2);int tot=unique(h+1,h+n+2)-h-1;build(1,1,tot);
        for(int i=1;i<=n;i++) p[i].y=lower_bound(h+1,h+tot+1,p[i].y)-h;sort(p+1,p+n+1);
        for(int i=1;i<=n;i++) {
            if(p[i].y<tot) update(1,p[i].y+1,tot,p[i].b);
            change(1,p[i].y,query(1,1,p[i].y)+p[i].b);
            if(p[i].y>1) update(1,1,p[i].y-1,p[i].a);
        }
        printf("%lld\n",query(1,1,tot));
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值