省选round1的时候dalao的推荐——atcoder的题目码量不大,但很巧妙,题目比较难找,挂个链冷静一下:http://s8pc-3.contest.atcoder.jp/tasks/s8pc_3_f
还行吧。。。
好久没写标记下传的线段树了(这次一写就是个双标记)居然能一遍写对核心代码(没开longlongRE了一发,改longlong就A了)
因为本来都是0,就好处理了
对于这道题我的理解是灌水(水泥):每次在a的地方灌b体积的水,如果平就往左灌
感性理解得到单调性(数学归纳可证),而且被灌的地方分成三个阶段:先填平,再竖直向上涨,最后在左边的一段填1
二分填到哪里位置,然后直接(用线段树)模拟就可以了,复杂度两个log
1 #include <bits/stdc++.h> 2 #define sum(x,y) que(1,1,n,x,y) 3 #define change(x,y,z) chan(1,1,n,x,y,z) 4 #define add(x,y,z) Plus(1,1,n,x,y,z) 5 #define mid (l+r>>1) 6 using namespace std; 7 long long sum[400000],fg[400000],ad[400000]; 8 long long n,m,a,b; 9 void down(int now,int l,int r) 10 { 11 if(fg[now]) 12 { 13 fg[now]+=ad[now]; 14 fg[now<<1]=fg[now]; 15 fg[now<<1|1]=fg[now]; 16 ad[now]=ad[now<<1]=ad[now<<1|1]=fg[now]=0; 17 sum[now<<1]=fg[now<<1]*(mid-l+1); 18 sum[now<<1|1]=fg[now<<1|1]*(r-mid); 19 } 20 if(ad[now]) 21 { 22 ad[now<<1]+=ad[now]; 23 ad[now<<1|1]+=ad[now]; 24 sum[now<<1]+=ad[now]*(mid-l+1); 25 sum[now<<1|1]+=ad[now]*(r-mid); 26 ad[now]=0; 27 } 28 } 29 void updata(int now) 30 { 31 sum[now]=sum[now<<1]+sum[now<<1|1]; 32 } 33 void chan(int now,int l,int r,int x,int y,long long z) 34 { 35 if(l==x && r==y) 36 { 37 fg[now]=z; 38 ad[now]=0; 39 sum[now]=z*(r-l+1); 40 return; 41 } 42 down(now,l,r); 43 if(x<=mid) 44 chan(now<<1,l,mid,x,min(mid,y),z); 45 if(y>mid) 46 chan(now<<1|1,mid+1,r,max(mid+1,x),y,z); 47 updata(now); 48 } 49 void Plus(int now,int l,int r,int x,int y,long long z) 50 { 51 if(l==x && r==y) 52 { 53 ad[now]+=z; 54 sum[now]+=z*(r-l+1); 55 return; 56 } 57 down(now,l,r); 58 if(x<=mid) 59 Plus(now<<1,l,mid,x,min(mid,y),z); 60 if(y>mid) 61 Plus(now<<1|1,mid+1,r,max(mid+1,x),y,z); 62 updata(now); 63 } 64 long long que(int now,int l,int r,int x,int y) 65 { 66 if(l==x && r==y) 67 return sum[now]; 68 down(now,l,r); 69 long long ret=0; 70 if(x<=mid) 71 ret+=que(now<<1,l,mid,x,min(y,mid)); 72 if(y>mid) 73 ret+=que(now<<1|1,mid+1,r,max(x,mid+1),y); 74 return ret; 75 } 76 int main() 77 { 78 scanf("%d%d",&n,&m); 79 for(int i=1;i<=m;i++) 80 { 81 scanf("%d%lld",&a,&b); 82 int l=1,r=a; 83 for(;l<r;) 84 if(sum(mid,mid)*(a-mid+1)-sum(mid,a)<=b) 85 r=mid; 86 else 87 l=mid+1; 88 b-=sum(l,l)*(a-l+1)-sum(l,a); 89 change(l,a,sum(l,l)); 90 add(l,a,b/(a-l+1)); 91 if(b%(a-l+1)) 92 add(l,l+b%(a-l+1)-1,1); 93 } 94 for(int i=1;i<=n;i++) 95 printf("%lld ",sum(i,i)); 96 return 0; 97 }