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

    题目链接:https://ac.nowcoder.com/acm/contest/881/I

    题目大意:

      给出n个点,每个点有a,b两个属性,让你从左下角到右上角划一条线,线的左边每个点的贡献是$a_{i}$,线的右边每个点的贡献是$b_{i}$,使得两部分的总和最大。即$max(sum_{iepsilon A}a_{i})+(sum_{iepsilon B}b_{i})$,且满足当$iepsilon A$,$jepsilon B$时,$x_{i}geq x_{j}$和$y_{i}leq y_{j}$。

    解题报告:

      先对y坐标进行离散化,考虑这条线经过若干个B点,如果当前点要取a,那么之前比它低的点的贡献都为a,如果当前点要取b,那么之前比它高的点的贡献都为b,然后还要考虑对当前点的b是否要选,区间维护dp,采用线段树。

    AC代码:

      1 #include<bits/stdc++.h>
      2 #define numm ch-48
      3 #define pd putchar(' ')
      4 #define pn putchar('
    ')
      5 #define pb push_back
      6 #define fi first
      7 #define se second
      8 #define fre1 freopen("1.txt","r",stdin)
      9 #define fre2 freopen("3.txt","w",stdout)
     10 #define bug cout<<"*******************"<<endl;
     11 #define debug(args...) cout<<#args<<"->"<<args<<"
    ";
     12 using namespace std;
     13 template <typename T>
     14 void read(T &res) {
     15     bool flag=false;char ch;
     16     while(!isdigit(ch=getchar())) (ch=='-')&&(flag=true);
     17     for(res=numm;isdigit(ch=getchar());res=(res<<1)+(res<<3)+numm);
     18     flag&&(res=-res);
     19 }
     20 template <typename T>
     21 void write(T x) {
     22     if(x<0) putchar('-'),x=-x;
     23     if(x>9) write(x/10);
     24     putchar(x%10+'0');
     25 }
     26 typedef long long ll;
     27 typedef unsigned long long ull;
     28 const int maxn=100010;
     29 const int maxm=505;
     30 const int mod=1e9+7;
     31 const int inv2=500000004;
     32 const int inf=0x3f3f3f3f;
     33 const ll INF=0x3f3f3f3f3f3f3f3f;
     34 const int N=32;
     35 struct node {
     36     int a,b,x,y;
     37     bool operator<(const node &z) {
     38         return x==z.x?y>z.y:x<z.x;
     39     }
     40 }p[maxn];
     41 struct ST {
     42     #define ls (k<<1)
     43     #define rs (k<<1|1)
     44     struct node {
     45         int l,r;
     46         ll maxx,lazy;
     47     }st[maxn<<2];
     48     void pushup(int k) {
     49         st[k].maxx=max(st[ls].maxx,st[rs].maxx);
     50     }
     51     void pushdown(int k) {
     52         st[ls].maxx+=st[k].lazy;
     53         st[ls].lazy+=st[k].lazy;
     54         st[rs].maxx+=st[k].lazy;
     55         st[rs].lazy+=st[k].lazy;
     56         st[k].lazy=0;
     57     }
     58     void build(int k,int l,int r) {
     59         st[k]=node{l,r,0,0};
     60         if(l==r) {
     61             st[k].maxx=-INF;
     62             st[k].lazy=0;
     63             return ;
     64         }
     65         int mid=(l+r)>>1;
     66         if(l<=mid) build(ls,l,mid);
     67         if(mid<r) build(rs,mid+1,r);
     68         pushup(k);
     69     }
     70     void add(int k,int l,int r,ll x) {   ///区间修改
     71         if(l>r) return ;
     72         if(st[k].l==l&&st[k].r==r) {
     73             st[k].maxx+=x;
     74             st[k].lazy+=x;
     75             return ;
     76         }
     77         if(st[k].lazy) pushdown(k);
     78         int mid=(st[k].l+st[k].r)>>1;
     79         if(mid>=r) add(ls,l,r,x);
     80         else if(mid<l) add(rs,l,r,x);
     81         else {
     82             add(ls,l,mid,x);
     83             add(rs,mid+1,r,x);
     84         }
     85         pushup(k);
     86     }
     87     void update(int k,int pos,ll x) {   ///单点修改进行取值最优化(dp)
     88         if(st[k].l==st[k].r) {
     89             st[k].maxx=max(st[k].maxx,x);
     90             return ;
     91         }
     92         if(st[k].lazy) pushdown(k);
     93         int mid=(st[k].l+st[k].r)>>1;
     94         if(mid>=pos) update(ls,pos,x);
     95         else if(mid<pos) update(rs,pos,x);
     96         pushup(k);
     97     }
     98     ll querymax(int k,int l,int r) {    ///区间查询
     99         if(l>r) return 0;
    100         if(st[k].l==l&&st[k].r==r) return st[k].maxx;
    101         if(st[k].lazy) pushdown(k);
    102         int mid=(st[k].l+st[k].r)>>1;
    103         if(mid>=r) return querymax(ls,l,r);
    104         else if(mid<l) return querymax(rs,l,r);
    105         else return max(querymax(ls,l,mid),querymax(rs,mid+1,r));
    106     }
    107 }wtz;
    108 int t[maxn];
    109 int main()
    110 {
    111 //    #define local
    112     #ifdef local
    113         fre1;
    114         fre2;
    115     #endif // local
    116     int n,m;
    117     while(scanf("%d",&n)!=EOF) {
    118         int tot=0;
    119         for(int i=1;i<=n;i++) {
    120             read(p[i].x),read(p[i].y);
    121             read(p[i].a),read(p[i].b);
    122             t[++tot]=p[i].y;
    123         }
    124         sort(t+1,t+1+n);
    125         tot=unique(t+1,t+1+n)-t-1;
    126         for(int i=1;i<=n;i++)   ///离散化
    127             p[i].y=lower_bound(t+1,t+1+tot,p[i].y)-t+1; ///线段树从1到p[i].y-1,p[i].y至少为2
    128         sort(p+1,p+1+n);
    129         tot++;  ///总区间加1,所以tot++
    130         wtz.build(1,1,tot);
    131         wtz.update(1,1,0);  ///新增高为0的点
    132         for(int i=1;i<=n;i++) {
    133             ll now=wtz.querymax(1,1,p[i].y);
    134             wtz.update(1,p[i].y,now+p[i].b);
    135             wtz.add(1,p[i].y+1,tot,p[i].b); ///对于当前点b选中的话,之前的比它高的都会被选
    136             wtz.add(1,1,p[i].y-1,p[i].a);   ///对于当前点a选中的话,之前的比它低的都会被选
    137         }
    138         write(wtz.st[1].maxx);pn;
    139     }
    140     return 0;
    141 }
    代码在这里!
  • 相关阅读:
    BZOJ 2002: [Hnoi2010]Bounce 弹飞绵羊(分块)
    BZOJ 2648 SJY摆棋子(KD Tree)
    Codeforces Round #441 D. Sorting the Coins(模拟)
    HDU 3400 Line belt (三分套三分)
    HDU 5919 Sequence II(主席树+区间不同数个数+区间第k小)
    HDU 5985 Lucky Coins(概率)
    HDU 5988 Coding Contest(浮点数费用流)
    HDU 5792 World is Exploding(树状数组+离散化)
    HDU 5791 Two(LCS求公共子序列个数)
    HDU 5787 K-wolf Number(数位dp)
  • 原文地址:https://www.cnblogs.com/wuliking/p/11372978.html
Copyright © 2011-2022 走看看