職業經營家庭菜園的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【hint】
拔除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)
其實也不算分析啦,就反思一下改了那麼久bug的原因。首先,我自己感覺出了一種神奇的線段樹維護方法,然後似乎被資料證明是錯的。接著求助了mlg,發現自己以為的很蠢的地方出錯了。。。臉好疼,最後是維護是順序調錯了(其實是一開始的思路影響的)。唉,不說了不說了。
1 #include2 #include3 #include4 #include5 #include6 #include7 #include8using
namespace
std;
9#define debug printf("zjyvegetable\n")
10#define int long long
11#define mid ((l+r)>>1)
12#define lp (p<<1)
13#define rp (p<<1|1)
14 inline int
read()
17while(isdigit(c))
18return a*b;19}
20const
int n=2e5+50,m=6e6+50,inf=123456789012345;21
struct
nodet[m],t[m];
24int n,q,b[n],h[n],p[n],c[n],f[n][2],ans=-inf;
25void spread(int
p)33
return;34
}35void pushup(int
p)38
void putin(int p,int l,int r,int k,int
z)43
spread(p);
44if(k<=mid)putin(lp,l,mid,k,z);
45else putin(rp,mid+1
,r,k,z);
46pushup(p);47}
48void add(int p,int l,int r,int l,int r,int
z)54
spread(p);
55if(r<=mid)add(lp,l,mid,l,r,z);
56else
if(l>mid)add(rp,mid+1
,r,l,r,z);
57else add(lp,l,mid,l,mid,z),add(rp,mid+1,r,mid+1
,r,z);
58pushup(p);59}
60int query(int p,int l,int r,int l,int
r)64
spread(p);
65if(r<=mid)return
query(lp,l,mid,l,r);
66else
if(l>mid)return query(rp,mid+1
,r,l,r);
67else
return max(query(lp,l,mid,l,mid),query(rp,mid+1,r,mid+1
,r));68}
6970
71void spread1(int
p)79
void pushup1(int
p)82
void putin1(int p,int l,int r,int k,int
z)87
spread1(p);
88if(k<=mid)putin1(lp,l,mid,k,z);
89else putin1(rp,mid+1
,r,k,z);
90pushup1(p);91}
92void add1(int p,int l,int r,int l,int r,int
z)98
spread1(p);
99if(r<=mid)add1(lp,l,mid,l,r,z);
100else
if(l>mid)add1(rp,mid+1
,r,l,r,z);
101else add1(lp,l,mid,l,mid,z),add1(rp,mid+1,r,mid+1
,r,z);
102pushup1(p);
103}
104int query1(int p,int l,int r,int l,int
r)108
spread1(p);
109if(r<=mid)return
query1(lp,l,mid,l,r);
110else
if(l>mid)return query1(rp,mid+1
,r,l,r);
111else
return max(query1(lp,l,mid,l,mid),query1(rp,mid+1,r,mid+1
,r));
112}
113signed main()
121 sort(b+1,b+n+1
);122 q=unique(b+1,b+n+1)-b-1
;123
for(int i=1;i<=n;i++)
126for(int i=1;i<=n;i++)
131for(int i=n;i>=1;i--)
136for(int i=1;i<=n;i++)ans=max(ans,f[i][1]+f[i][0]-p[i]);
137 printf("
%lld\n
",ans);
138return0;
139 }
有趣的家庭菜園
對家庭菜園有興趣的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...
JOI 有趣的有趣的家庭菜園Fgarden
職業經營家庭菜園的joi君每年在自家的田地中種植一種叫做ioi草的植物。ioi草的種子在冬天被播下,春天會發芽並生長至乙個固定的高度。到了秋天,一些ioi草會結出美麗的果實,並被收穫,其他的ioi草則會在冬天枯萎。joi君的田地沿東西方向被劃分為n個區域,從西側開始的第i個區域中種植著ioi草i。在...