【有趣的有趣的家庭菜园】题解

来源:互联网 发布:华一软件 编辑:程序博客网 时间:2024/04/28 02:40

分析

设f[i]指1~i没有比i更高的草是,1~i的收益。
显然转移为,当h[j]<=h[i]

f[i]=max(f[j]j<k<ih[k]>h[i]c[k])+p[i]

然后设g[i]指i~n没有比i更高的草是,i~n的收益。转移同上。答案就是max(f[i]+g[i]-p[i]),O(n^3),超时。
如何优化呢?由于n<=100000,就离散化h,以高度搞个有标记线段树,记录
max(f[j]j<k<ih[k]>h[i]c[k])
。然后每次把小于等于h[i]的线段树的最大值取出来,把f[i]放入线段树,再把小于h[i]的都减去c[i]。

#include <cmath>#include <iostream>#include <cstdio>#include <cstdlib>#include <cstring>#include <algorithm>#include <queue>const long long maxlongint=2147483647;using namespace std;long long tree[400000],f[200000],g[200000],n,m,ans,tot,h[200000],p[200000],c[200000],bef[200000],reh[200000],dee[400000];void q(long long l,long long r){    long long i=l,j=r,mid=reh[(l+r)/2],e;    while(i<j)    {        while(reh[i]<mid) i++;        while(reh[j]>mid) j--;        if(i<=j)        {            e=reh[i];            reh[i]=reh[j];            reh[j]=e;            e=bef[i];            bef[i]=bef[j];            bef[j]=e;            i++;            j--;        }    }    if(i<r) q(i,r);    if(l<j) q(l,j);}long long disc(){    long long k;    q(1,n);    k=0;    for(long long i=1;i<=n;i++)    {        if(reh[i]!=reh[i-1])            k++;        h[bef[i]]=k;    }}long long find(long long v,long long l,long long r,long long x,long long y){     if(l==x && r==y)    {        return tree[v];    }    if(tree[v*2]!=tree[0])    {        tree[v*2]-=dee[v];        dee[v*2]+=dee[v];    }    else    {        tree[v*2]=-dee[v];        dee[v*2]+=dee[v];    }    if(tree[v*2+1]!=tree[0])    {        tree[v*2+1]-=dee[v];        dee[v*2+1]+=dee[v];    }    else    {        tree[v*2+1]=-dee[v];        dee[v*2+1]+=dee[v];    }    dee[v]=0;    long long mid=(l+r)/2,t,t1;    if(y<=mid)    {        return find(v*2,l,mid,x,y);    }            else                if(x>mid)                    return find(v*2+1,mid+1,r,x,y);                        else                         {                            return max(find(v*2,l,mid,x,mid),find(v*2+1,mid+1,r,mid+1,y));                        }    return t;}long long put(long long v,long long l,long long r,long long hi,long long pu){    if(l==r)    {        tree[v]=max(tree[v],pu);        return 0;    }    if(tree[v*2]!=tree[0])    {        tree[v*2]-=dee[v];        dee[v*2]+=dee[v];    }    else    {        tree[v*2]=-dee[v];        dee[v*2]+=dee[v];    }    if(tree[v*2+1]!=tree[0])    {        tree[v*2+1]-=dee[v];        dee[v*2+1]+=dee[v];    }    else    {        tree[v*2+1]=-dee[v];        dee[v*2+1]+=dee[v];    }    dee[v]=0;    long long mid=(l+r)/2;    if(hi<=mid)    {           put(v*2,l,mid,hi,pu);        tree[v]=max(tree[v*2+1],tree[v*2]);    }    else    {        put(v*2+1,mid+1,r,hi,pu);        tree[v]=max(tree[v*2],tree[v*2+1]);     }    tree[v]=max(tree[v*2],tree[v*2+1]);}long long de(long long v,long long l,long long r,long long x,long long y,long long d){    if(l==x && r==y)    {        dee[v]+=d;        tree[v]-=d;        return 0;    }    if(tree[v*2]!=tree[0])    {        tree[v*2]-=dee[v];        dee[v*2]+=dee[v];    }    else    {        tree[v*2]=-dee[v];        dee[v*2]+=dee[v];    }    if(tree[v*2+1]!=tree[0])    {        tree[v*2+1]-=dee[v];        dee[v*2+1]+=dee[v];    }    else    {        tree[v*2+1]=-dee[v];        dee[v*2+1]+=dee[v];    }    dee[v]=0;    long long mid=(l+r)/2;    if(y<=mid)        de(v*2,l,mid,x,y,d);            else                if(x>mid)                    de(v*2+1,mid+1,r,x,y,d);                        else de(v*2,l,mid,x,mid,d),de(v*2+1,mid+1,r,mid+1,y,d);    tree[v]=max(tree[v*2],tree[v*2+1]); }int main(){    scanf("%lld\n",&n);    long long i,j,k;    for(i=1;i<=n;i++)    {        scanf("%lld%lld%lld\n",&reh[i],&p[i],&c[i]);        bef[i]=i;    }    disc();    memset(tree,200,sizeof(tree));    put(1,0,n,0,0);    memset(dee,0,sizeof(dee));    for(i=1;i<=n;i++)    {        f[i]=find(1,0,n,0,h[i])+p[i];        put(1,0,n,h[i],f[i]);        de(1,0,n,0,h[i]-1,c[i]);    }    memset(tree,200,sizeof(tree));    put(1,0,n,0,0);    memset(dee,0,sizeof(dee));    ans=0;    for(i=n;i>=1;i--)    {        g[i]=find(1,0,n,0,h[i])+p[i];        put(1,0,n,h[i],g[i]);        de(1,0,n,0,h[i]-1,c[i]);    }    for(i=1;i<=n;i++)        ans=max(ans,f[i]-p[i]+g[i]);    printf("%lld\n",ans);}
1 0
原创粉丝点击