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

分析

设f[i]指1~i没有比i更高的草是,1~i的收益。
显然转移为,当h[j]<=h[i]\[f[i]=max(f[j]-\sum_{j<k<i 且 h[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]-\sum_{j<k<i 且 h[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);
}



猜你喜欢

转载自www.cnblogs.com/chen1352/p/9008558.html