您的位置:首页 > 其它

JOI 有趣的有趣的家庭菜园Fgarden

2017-09-27 19:47 309 查看


【题目描述】

职业经营家庭菜园的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
ce32
50 20


【样例输出】

320


【提示】

拔除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)
最终有贡献的草一定是单调上升再单调下降
那么方程f[i]=max(f[j]+v[i]);h[j]<=h[i] j<=i
g[i]=max(g[j]+v[i]);h[j]<=h[i] j>=i
答案取f[i]+g[i]-v[i]
将高度离散化 用线段树优化转移
考虑一颗草种进去 他会对后面的比他矮的草有影响(需要拔掉这颗)那么就对线段树[1,h[i]]这个区间减上cost[i] 
时间复杂度O(nlogn)
#include<cstdio>
#include<algorithm>
#include<cstring>
using namespace std;
const int maxn=200000+10;
typedef long long LL;
LL f[maxn],g[maxn];
#define INF 1<<64-1
#define lc rt<<1
#define rc rt<<1|1
LL maxx[maxn<<2],tag[maxn<<2];
LL h[maxn],v[maxn],c[maxn],B[maxn],hash[maxn];
int tot;
inline void pushdown(int o){
if(tag[o]!=0){
maxx[o<<1]+=tag[o];
maxx[o<<1|1]+=tag[o];
tag[o<<1]+=tag[o];
tag[o<<1|1]+=tag[o];
tag[o]=0;
}
}
inline int bs(LL x){
int l=1,r=tot;
while(l+1<r){
int mid=(l+r)>>1;
if(hash[mid]>=x)
r=mid;
else l=mid+1;
}
if(hash[l]==x)
return l;
return r;
}
inline LL qmax(int o,int l,int r,int L,int R){
if(L<=l&&r<=R)
return maxx[o];
int mid=(l+r)>>1;
LL ans=0;
int vis=0;
pushdown(o);
if(L<=mid){
if(!vis){
ans=qmax(o<<1,l,mid,L,R);
vis=1;
}
else ans=max(ans,qmax(o<<1,l,mid,L,R));
}
if(R>mid){
if(!vis){
ans=qmax(o<<1|1,mid+1,r,L,R);
vis=1;
}
else ans=max(ans,qmax(o<<1|1,mid+1,r,L,R));
}
return ans;
}
inline void add(int o,int l,int r,int L,int R,LL x){
if(L<=l&&r<=R){
maxx[o]+=x;
tag[o]+=x;
return;
}
int mid=(l+r)>>1;
pushdown(o);
if(L<=mid)
add(o<<1,l,mid,L,R,x);
if(R>mid)
add(o<<1|1,mid+1,r,L,R,x);
maxx[o]=max(maxx[o<<1],maxx[o<<1|1]);
}
inline void change(int o,int l,int r,int x,LL y){
if(l==r&&l==x){
maxx[o]=max(maxx[o],y);
return;
}
int mid=(l+r)>>1;
pushdown(o);
if(x<=mid)
change(o<<1,l,mid,x,y);
else change(o<<1|1,mid+1,r,x,y);
maxx[o]=max(maxx[o<<1],maxx[o<<1|1]);
}
int main(){
freopen("Fgarden.in","r",stdin);
freopen("Fgarden.out","w",stdout);
int n;
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%lld %lld %lld",&h[i],&v[i],&c[i]);
B[i]=h[i];
}
sort(B+1,B+n+1);
hash[++tot]=B[1];
for(int i=2;i<=n;i++)
if(B[i]!=B[i-1])
hash[++tot]=B[i];
memset(maxx,0,sizeof(maxx));
memset(tag,0,sizeof(tag));
for(int i=1;i<=n;i++){
int u=bs(h[i]);
f[i]=v[i]+qmax(1,1,tot,1,u);
add(1,1,tot,1,u,-c[i]);
change(1,1,tot,u,f[i]);
}
memset(maxx,0,sizeof(maxx));
memset(tag,0,sizeof(tag));
for(int i=n;i>=1;i--){
int u=bs(h[i]);
g[i]=v[i]+qmax(1,1,tot,1, u);
add(1,1,tot,1,u,-c[i]);
change(1,1,tot,u,g[i]);
}
LL ans=0;
for(int i=1;i<=n;i++)
ans=max(ans,f[i]+g[i]-v[i]);
printf("%lld\n",ans);
/*for(int i=1;i<=n;i++)
printf("%lld\n",f[i]);*/
//for(int i=1;i<=n;i++)
// printf("%lld\n",g[i]);
return 0;
}

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: