atcoder square869120Contest#3 F 寿司

省选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\n",sum(i,i));
96     return 0;
97 }

 

posted @ 2017-05-09 15:47  汪立超  阅读(150)  评论(0编辑  收藏