AtCoder square869120 Contest #3 F sushi
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!
题目链接:sushi
正解:线段树
解题报告:
考虑$a[i]>=a[i+1]$恒成立,那么序列为一段段相等的数,类似于灌水的问题。
那么用线段树维护每个点的权值,不难发现,每次$add$操作,应该是先填平差距,有剩余的话就整体上升,余下的部分补给一段前缀。
那么只需要用线段树来维护就好了,在线段树上维护$set$和$add$标记,$pushdown$的时候注意先后顺序。
//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; } //有志者,事竟成,破釜沉舟,百二秦关终属楚;苦心人,天不负,卧薪尝胆,三千越甲可吞吴。
本文作者:ljh2000
作者博客:http://www.cnblogs.com/ljh2000-jump/
转载请注明出处,侵权必究,保留最终解释权!