歌名 - 歌手
0:00

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

    分析

    设f[i]指1i没有比i更高的草是,1i的收益。
    显然转移为,当h[j]<=h[i]$$f[i]=max(f[j]-\sum_{j<k<i 且 h[k]>h[i] }{c[k]})+p[i]$$
    然后设g[i]指in没有比i更高的草是,in的收益。转移同上。答案就是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);
    }
    
    
    
    
    
    posted @ 2018-05-08 15:38  无尽的蓝黄  阅读(168)  评论(0编辑  收藏  举报