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

2021-08-08 19:41:57 字數 3236 閱讀 5979

職業經營家庭菜園的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 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。在...