本文版權歸ljh2000和博客園共有,歡迎轉載,但須保留此聲明,並給出原文連接,謝謝合做。node
本文做者:ljh2000
做者博客:http://www.cnblogs.com/ljh2000-jump/
轉載請註明出處,侵權必究,保留最終解釋權!ios
題目連接:sushispa
正解:線段樹code
解題報告:blog
考慮$a[i]>=a[i+1]$恆成立,那麼序列爲一段段相等的數,相似於灌水的問題。get
那麼用線段樹維護每一個點的權值,不難發現,每次$add$操做,應該是先填平差距,有剩餘的話就總體上升,餘下的部分補給一段前綴。博客
那麼只須要用線段樹來維護就行了,在線段樹上維護$set$和$add$標記,$pushdown$的時候注意前後順序。string
//It is made by ljh2000 //有志者,事竟成,破釜沉舟,百二秦關終屬楚;苦心人,天不負,臥薪嚐膽,三千越甲可吞吳。 #include <algorithm> #include <iostream> #include <cstring> #include <vector> #include <cstdio> #include <string> #include <queue> #include <cmath> #include <ctime> #define lc root<<1 #define rc root<<1|1 using namespace std; typedef long long LL; const int MAXN = 200011; int n,Q; struct node{ LL set,add,sum; }a[MAXN*3]; inline void update(int root){ a[root].sum=a[lc].sum+a[rc].sum; } inline int getint(){ int w=0,q=0; char c=getchar(); while((c<'0'||c>'9') && c!='-') c=getchar(); if(c=='-') q=1,c=getchar(); while (c>='0'&&c<='9') w=w*10+c-'0',c=getchar(); return q?-w:w; } inline void pushdown(int root,int l,int r){ if(a[root].set==0 && a[root].add==0) return ; if(l==r) return ; int mid=(l+r)>>1; if(a[root].set>0) { a[lc].set=a[rc].set=a[root].set; a[lc].sum=1LL*a[root].set*(mid-l+1); a[rc].sum=1LL*a[root].set*(r-mid); a[lc].add=a[rc].add=a[root].set=0; } if(a[root].add>0) { a[lc].add+=a[root].add; a[rc].add+=a[root].add; a[lc].sum+=1LL*a[root].add*(mid-l+1); a[rc].sum+=1LL*a[root].add*(r-mid); a[root].add=0; } } inline void modify(int root,int l,int r,int ql,int qr,LL val){ pushdown(root,l,r); if(ql<=l && r<=qr) { a[root].set=val; a[root].add=0; a[root].sum=1LL*(r-l+1)*val; return ; } int mid=(l+r)>>1; if(ql<=mid) modify(lc,l,mid,ql,qr,val); if(qr>mid) modify(rc,mid+1,r,ql,qr,val); update(root); } inline void add(int root,int l,int r,int ql,int qr,LL val){ pushdown(root,l,r); if(ql<=l && r<=qr) { a[root].sum+=1LL*val*(r-l+1); a[root].add+=val; return ; } int mid=(l+r)>>1; if(ql<=mid) add(lc,l,mid,ql,qr,val); if(qr>mid) add(rc,mid+1,r,ql,qr,val); update(root); } inline LL query(int root,int l,int r,int ql,int qr){ if(ql<=l && r<=qr) return a[root].sum; pushdown(root,l,r); int mid=(l+r)>>1; if(qr<=mid) return query(lc,l,mid,ql,qr); else if(ql>mid) return query(rc,mid+1,r,ql,qr); return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr); } inline void dfs(int root,int l,int r){ if(l==r) { printf("%lld\n",a[root].sum); return ; } pushdown(root,l,r); int mid=(l+r)>>1; dfs(lc,l,mid); dfs(rc,mid+1,r); } inline void work(){ n=getint(); Q=getint(); int x; LL y; int l,r,mid,pos; while(Q--) { x=getint(); scanf("%lld",&y); if(x==1) { add(1,1,n,1,1,y); continue; } l=1; r=x; pos=0; while(l<=r) { mid=(l+r)>>1; if(1LL*query(1,1,n,mid,mid)*(x-mid+1)-query(1,1,n,mid,x) <= y) r=mid-1; else l=mid+1,pos=mid; } y-=1LL*query(1,1,n,pos+1,pos+1)*(x-pos)-query(1,1,n,pos+1,x); modify(1,1,n,pos+1,x, query(1,1,n,pos+1,pos+1) ); if(y/(x-pos)) add(1,1,n,pos+1,x,y/(x-pos)); if(y%(x-pos)) add(1,1,n,pos+1,pos+y%(x-pos),1); } dfs(1,1,n); } int main() { work(); return 0; } //有志者,事竟成,破釜沉舟,百二秦關終屬楚;苦心人,天不負,臥薪嚐膽,三千越甲可吞吳。