職業經營家庭菜園的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君能獲得的最大利益
722 60 30
46 40 30
36 100 50
11 140 120
38 120 20
24 90 60
53 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#include#includeusing 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)
}inline int bs(ll x)
if(hash[l]==x)
return l;
return r;
}inline ll qmax(int o,int l,int r,int l,int r)
else ans=max(ans,qmax(o<<1,l,mid,l,r));
} if(r>mid)
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)
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)
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()
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++)
memset(maxx,0,sizeof(maxx));
memset(tag,0,sizeof(tag));
for(int i=n;i>=1;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;
}
有趣的家庭菜園
對家庭菜園有興趣的joi君每年在自家的田地中種植一種叫做ioi草的植物。joi君的田地沿東西方向被劃分為n個區域,由西到東標號為1 n。ioi草一共有n株,每個區域種植著一株。在第i個區域種植的ioi草,在春天的時候高度會生長至hi,此後便不再生長。為了觀察春天的樣子而出行的joi君注意到了ioi草...
ssoj2455有趣的有趣的家庭菜園(線段樹)
題意 有乙個n塊的線性菜園,每塊菜園只有照到陽光 左右兩邊沒有遮擋 才能收穫果實賣出去價值為p,也可以除去費用為c,問最大利益是多少 思路 列舉n塊田地i為最高處,ans即為其左邊最大利潤加右邊最大利潤。dp o n 2 會超時。用線段樹維護左邊 右邊 最大值,點更新,與區間值的更改。include...
有趣的有趣的家庭菜園 線段樹優化dp
職業經營家庭菜園的joi君每年在自家的田地中種植一種叫做ioi草的植物。ioi草的種子在冬天被播下,春天會發芽並生長至乙個固定的高度。到了秋天,一些ioi草會結出美麗的果實,並被收穫,其他的ioi草則會在冬天枯萎。joi君的田地沿東西方向被劃分為n個區域,從西側開始的第i個區域中種植著ioi草i。在...