日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

BZOJ4293 Siano

發(fā)布時間:2023/12/10 编程问答 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 BZOJ4293 Siano 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

題頭:

描述
農(nóng)夫Byteasar買了一片n畝的土地,他要在這上面種草。 他在每一畝土地上都種植了一種獨一無二的草,其中,第i畝土地的草每天會長高a[i]厘米。 Byteasar一共會進行m次收割,其中第i次收割在第d[i]天,并把所有高度大于等于b[i]的部分全部割去。Byteasar想知道,每次收割得到的草的高度總和是多少,你能幫幫他嗎?
Input
第一行包含兩個正整數(shù)n,m(1<=n,m<=500000),分別表示畝數(shù)和收割次數(shù)。 第二行包含n個正整數(shù),其中第i個數(shù)為ai,依次表示每畝種植的草的生長能力。 接下來m行,每行包含兩個正整數(shù)d[i],bi,依次描述每次收割。 數(shù)據(jù)保證d[1] < d[2] <… < d[m],并且任何時刻沒有任何一畝草的高度超過10^12。
Output
輸出m行,每行一個整數(shù),依次回答每次收割能得到的草的高度總和。
樣例輸入
4 4
1 2 4 3
1 1
2 2
3 0
4 4
樣例輸出
6
6
18
0

仔細讀題
我們需要兩個標(biāo)記
一個mark進行區(qū)間加的操作(mark維護天數(shù),實際增加的值是mark[ i ]*a[ i ])
還需要一個marks進行區(qū)間更改為的操作
然后對于每次輸入
mark增加的值為這一次輸入的時間減上一次輸入的時間
然后我們維護兩個值:區(qū)間和和區(qū)間最大值(兩次區(qū)間和相減即使所求答案,區(qū)間最大值是方便進行區(qū)間更改為的操作,因為這樣我們只需要下傳標(biāo)記到區(qū)間最大值大于b[ i ]的區(qū)間)
維護區(qū)間和需要把區(qū)間a的值的和乘上mark,區(qū)間最大值加上天數(shù)乘區(qū)間a的最大值;
我們只需要先從小到大排個序,保證單調(diào)性,這樣找到最后一個高度小于b[ i ]的位置,我們就可以直接把從這兒往后都打上標(biāo)記

代碼如下

//siano #include<bits/stdc++.h> using namespace std; #define ll long long inline ll read(){char ch;while((ch=getchar())<'0'||ch>'9'){;}ll res=ch-'0';while((ch=getchar())>='0'&&ch<='9')res=res*10+ch-'0';return res; } long long a[500005],tre[2000007],mark[2000007],maxn[2000007],sum[500005],marks[2000007],d1; //tre:記錄區(qū)間和,sum int n,m,l[2000007],r[2000007]; inline ll max(ll a,ll b) {return a>b?a:b; } inline void buildtree(int p,int st,int end){l[p]=st,r[p]=end,mark[p]=0,marks[p]=-1; //marks初始化為-1,不能初始化為0(有可能是更改為0)if(st==end){tre[p]=maxn[p]=0;return;}int mid=(st+end)>>1;buildtree(p<<1,st,mid),buildtree((p<<1)+1,mid+1,end); } inline void pushup(int root) //向上傳遞 {maxn[root]=max(maxn[(root<<1)],maxn[(root<<1)+1]);tre[root]=tre[(root<<1)]+tre[(root<<1)+1]; } inline void pushnow(int root,ll v){ //用mark更改區(qū)間mark[root]+=v;tre[root]+=v*(sum[r[root]]-sum[l[root]-1]);maxn[root]+=v*a[r[root]]; } inline void pushnown(int root,ll k) //用marks更改區(qū)間 {marks[root]=k;maxn[root]=k;tre[root]=k*(r[root]-l[root]+1);mark[root]=0; //因為更改區(qū)間以后前面的操作打下的mark,對當(dāng)前答案不會有影響,所以把mark變?yōu)?; } inline void pushDown(int root) //向下傳遞 {if(marks[root]!=-1){pushnown((root<<1),marks[root]);pushnown((root<<1)+1,marks[root]);marks[root]=-1;}if(mark[root]){pushnow((root<<1),mark[root]);pushnow((root<<1)+1,mark[root]);mark[root]=0;} } inline void modify(int root,int ql,int qr,ll v){ //更改區(qū)間值if(ql>r[root]||qr<l[root])return;if(ql<=l[root]&&r[root]<=qr){pushnown(root,v);return;}pushDown(root);int mid=(l[root]+r[root])>>1;if(qr<=mid)modify((root<<1),ql,qr,v);else if(ql>mid)modify((root<<1)+1,ql,qr,v);else modify((root<<1),ql,mid,v),modify((root<<1)+1,mid+1,qr,v);pushup(root); } inline ll query(int root,ll v){ //查找第一個小于等于b[ i ]的位置 if(l[root]==r[root])return l[root];pushDown(root);if(maxn[(root<<1)]<=v)return query((root<<1)+1,v);return query((root<<1),v); }int main(){n=read(),m=read();for(int i=1;i<=n;i++){a[i]=read();}sort(a+1,a+1+n);buildtree(1,1,n);for(int i=1;i<=n;i++)sum[i]=sum[i-1]+a[i];d1=0;for(int i=1;i<=m;i++){ll d2=read(),b=read();maxn[1]+=(d2-d1)*a[n],tre[1]+=(d2-d1)*sum[n],mark[1]+=(d2-d1);if(maxn[1]<=b){puts("0"),d1=d2;continue;}ll res=tre[1];int pos=query(1,b);modify(1,pos,n,b);cout<<res-tre[1]<<'\n',d1=d2;}return 0; }

轉(zhuǎn)載于:https://www.cnblogs.com/stargazer-cyk/p/10366527.html

總結(jié)

以上是生活随笔為你收集整理的BZOJ4293 Siano的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。