• 有趣的有趣的家庭菜园——线段树优化dp


    有趣的有趣的家庭菜园

    职业经营家庭菜园的JOI君每年在自家的田地中种植一种叫做IOI草的植物。IOI草的种子在冬天被播下,春天会发芽并生长至一个固定的高度。到了秋天,一些IOI草会结出美丽的果实,并被收获,其他的IOI草则会在冬天枯萎。
    JOI君的田地沿东西方向被划分为N个区域,从西侧开始的第i个区域中种植着IOI草i。在第i个区域种植的IOI草,在春天的时候高度会生长至Hi,此后便不再生长。如果IOI草i会结出果实,那么将会获得Pi的收益,否则没有收益。
    春天到了,查看田地样子的JOI君决定拔掉一些种植的IOI草,使利益最大化。拔掉IOI草i需要Ci的花销,拔掉的IOI草会立刻枯萎。IOI草只能在春天被拔掉,夏天和秋天不能拔掉IOI草。
    IOI草是一种非常依靠阳光的植物,如果在夏天某个区域的IOI草的东侧和西侧都有比它高的IOI草存在,那么这株IOI草在秋天便不会结出果实。换句话说,为了让没有被拔掉的IOI草i在秋天结出果实,到了夏天的时候,以下两个条件至少满足一个:
    1.对于任意1<=j<=i-1,Hj<=Hi或IOI草j已经被拔除
    2.对于任意i+1<=j<=N,Hj<=Hi或IOI草j已经被拔除
    用最终收获的果实的总价格减掉拔除IOI草的花销的总和,即为JOI君的收益。那么JOI君能从IOI草中获取的最大利益到底有多少呢?

    第一行一个正整数N,表示田地被分为了N个区域。
    接下来N行,第i行(1<=i<=N)三个空白分割的正整数Hi,Pi,Ci,表示第i株IOI草在春天时高度会生长至Hi,秋天收获的果实的价格为Pi,拔除所需费用为Ci。

    输出一行一个整数,表示JOI君能获得的最大利益

    7
    22 60 30
    46 40 30
    36 100 50
    11 140 120
    38 120 20
    24 90 60
    53 50 20

    320
    HINT】
    拔除IOI草2和IOI草7,剩余的IOI草如下图所示:

    IOI草1、3、5、6的果实价格分别为60、100、120、90,拔除IOI草2和IOI草7的花销分别为30、20,总收益为320,这是所有方案中的最大值。

    对于30%的数据,N<=20
    对于45%的数据,N<=300
    对于60%的数据,N<=5000
    对于100%的数据:
    3<=N<=10^5
    1<=Hi<=10^9 (1<=i<=N)
    1<=Pi<=10^9 (1<=i<=N)
    1<=Ci<=10^9 (1<=i<=N)

    分析:

    其实也不算分析啦,就反思一下改了那么久bug的原因。首先,我自己感觉出了一种神奇的线段树维护方法,然后似乎被数据证明是错的。接着求助了mlg,发现自己以为的很蠢的地方出错了。。。脸好疼,最后是维护是顺序调错了(其实是一开始的思路影响的)。唉,不说了不说了。

    代码:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cstring>
      4 #include<cmath>
      5 #include<queue>
      6 #include<algorithm>
      7 #include<vector>
      8 using namespace std;
      9 #define debug printf("zjyvegetable
    ")
     10 #define int long long
     11 #define mid ((l+r)>>1)
     12 #define lp (p<<1)
     13 #define rp (p<<1|1)
     14 inline int read(){
     15     int a=0,b=1;char c=getchar();
     16     while(!isdigit(c)){if(c=='-')b=-1;c=getchar();}
     17     while(isdigit(c)){a=a*10+c-'0';c=getchar();}
     18     return a*b;
     19 }
     20 const int N=2e5+50,M=6e6+50,inf=123456789012345;
     21 struct node{
     22     int maxn,lazy;
     23 }t[M],T[M];
     24 int n,q,b[N],h[N],p[N],c[N],f[N][2],ans=-inf;
     25 void spread(int p){
     26     if(t[p].lazy){
     27         t[lp].maxn+=t[p].lazy;
     28         t[rp].maxn+=t[p].lazy;
     29         t[lp].lazy+=t[p].lazy;
     30         t[rp].lazy+=t[p].lazy;
     31         t[p].lazy=0;
     32     }
     33     return;
     34 }
     35 void pushup(int p){
     36     t[p].maxn=max(t[lp].maxn,t[rp].maxn);
     37 }
     38 void putin(int p,int l,int r,int k,int z){
     39     if(l==r){
     40         if(z>t[p].maxn)t[p].maxn=z;
     41         return;
     42     }
     43     spread(p);
     44     if(k<=mid)putin(lp,l,mid,k,z);
     45     else putin(rp,mid+1,r,k,z);
     46     pushup(p);
     47 }
     48 void add(int p,int l,int r,int L,int R,int z){
     49     if(l==L&&r==R){
     50         t[p].maxn+=z;
     51         t[p].lazy+=z;
     52         return;
     53     }
     54     spread(p);
     55     if(R<=mid)add(lp,l,mid,L,R,z);
     56     else if(L>mid)add(rp,mid+1,r,L,R,z);
     57     else add(lp,l,mid,L,mid,z),add(rp,mid+1,r,mid+1,R,z);
     58     pushup(p);
     59 }
     60 int query(int p,int l,int r,int L,int R){
     61     if(l==L&&r==R){
     62         return t[p].maxn;
     63     }
     64     spread(p);
     65     if(R<=mid)return query(lp,l,mid,L,R);
     66     else if(L>mid)return query(rp,mid+1,r,L,R);
     67     else return max(query(lp,l,mid,L,mid),query(rp,mid+1,r,mid+1,R));
     68 }
     69 
     70 
     71 void spread1(int p){
     72     T[lp].maxn+=T[p].lazy;
     73     T[rp].maxn+=T[p].lazy;
     74     T[lp].lazy+=T[p].lazy;
     75     T[rp].lazy+=T[p].lazy;
     76     T[p].lazy=0;
     77     return;
     78 }
     79 void pushup1(int p){
     80     T[p].maxn=max(T[lp].maxn,T[rp].maxn);
     81 }
     82 void putin1(int p,int l,int r,int k,int z){
     83     if(l==r){
     84         if(z>T[p].maxn)T[p].maxn=z;
     85         return;
     86     }
     87     spread1(p);
     88     if(k<=mid)putin1(lp,l,mid,k,z);
     89     else putin1(rp,mid+1,r,k,z);
     90     pushup1(p);
     91 }
     92 void add1(int p,int l,int r,int L,int R,int z){
     93     if(l==L&&r==R){
     94         T[p].maxn+=z;
     95         T[p].lazy+=z;
     96         return;
     97     }
     98     spread1(p);
     99     if(R<=mid)add1(lp,l,mid,L,R,z);
    100     else if(L>mid)add1(rp,mid+1,r,L,R,z);
    101     else add1(lp,l,mid,L,mid,z),add1(rp,mid+1,r,mid+1,R,z);
    102     pushup1(p);
    103 }
    104 int query1(int p,int l,int r,int L,int R){
    105     if(l==L&&r==R){
    106         return T[p].maxn;
    107     }
    108     spread1(p);
    109     if(R<=mid)return query1(lp,l,mid,L,R);
    110     else if(L>mid)return query1(rp,mid+1,r,L,R);
    111     else return max(query1(lp,l,mid,L,mid),query1(rp,mid+1,r,mid+1,R));
    112 }
    113 signed main(){
    114     //freopen("herbary.in","r",stdin);
    115     //freopen("herbary.out","w",stdout);
    116     n=read();
    117     for(int i=1;i<=n;i++){
    118         b[i]=h[i]=read();p[i]=read();
    119         c[i]=read();
    120     }
    121     sort(b+1,b+n+1);
    122     q=unique(b+1,b+n+1)-b-1;
    123     for(int i=1;i<=n;i++){
    124         h[i]=lower_bound(b+1,b+q+1,h[i])-b;
    125     }
    126     for(int i=1;i<=n;i++){
    127         f[i][0]=query(1,1,q,1,h[i])+p[i];
    128         if(h[i])add(1,1,q,1,h[i],-c[i]);//按公式来,先减再插
    129         putin(1,1,q,h[i],f[i][0]);
    130     }
    131     for(int i=n;i>=1;i--){
    132         f[i][1]=query1(1,1,q,1,h[i])+p[i];
    133         if(h[i])add1(1,1,q,1,h[i],-c[i]);
    134         putin1(1,1,q,h[i],f[i][1]);
    135     }
    136     for(int i=1;i<=n;i++)ans=max(ans,f[i][1]+f[i][0]-p[i]);
    137     printf("%lld
    ",ans);
    138     return 0;
    139 }
  • 相关阅读:
    poj3083(Children of the Candy Corn)
    poj3278(Catch That Cow)
    poj2996(Help Me with the Game)
    poj2993(Emag eht htiw Em Pleh)
    js 对多sheet Excel赋值操作
    学习进度总结(三)
    学习进度总结(二)
    学习进度总结(一)
    《人月神话》阅读笔记(1)
    Android studio的安装与使用
  • 原文地址:https://www.cnblogs.com/zjy1412/p/13394216.html
Copyright © 2020-2023  润新知