【北京集训测试赛(七)/BZOJ4631】踩气球(Balloon)-线段树-STL-Vector

Problem 踩气球

题目大意

给m个区间和一个数列,每次对其中一个数减一,强制在线求每次操作后区间内数字全都为0的区间。

Solution

对于数列开一个线段树。对于线段树每一个点开一个vector存区间的id。

这样我们一共最多会存下$\log m$个id。

对于每次操作,维护线段树sum值。

当我们将一个数减到了零,那么对于到根路径上的每一个点扫一遍。

如果这个点的sum值变成零了那么就扫一遍这个点的vector

判断这个id的区间是否被减完了(额外开一个数组维护就行了)

如果减成零了那么就ans++。最后我们清空这个vector。

这样下来,因为每个vector中的东西最多只会访问一遍(然后就删了),

所以复杂度是$O(q \log n+\log m)$

AC Code

 1 #include <iostream>
 2 #include <cstdio>
 3 #include <cstring>
 4 #include <vector>
 5 using namespace std;
 6 struct Node{
 7     int l,r,sum;
 8     vector<int> v;
 9 }a[500010];
10 int lastans=0,bal[100010],ans=0,x,f[100010];
11 int q,l,r,m,n;
12 void sg_update(int now){
13     if(a[now].sum)return;
14     for(vector<int>::iterator it=a[now].v.begin();it!=a[now].v.end();it++){
15         bal[*it]-=a[now].r-a[now].l+1;
16         if(!bal[*it])ans++;
17     }
18     a[now].v.clear();
19 }
20 void sg_build(int l,int r,int now){
21     a[now].l=l;a[now].r=r;
22     if(l==r){
23         a[now].sum=f[l];
24         return;
25     }
26     int mid=(l+r)>>1;
27     sg_build(l,mid,now<<1);
28     sg_build(mid+1,r,now<<1|1);
29     a[now].sum=a[now<<1].sum+a[now<<1|1].sum;
30     return;
31 }
32 int sg_delete(int now,int x){
33     if(a[now].l==a[now].r){
34         a[now].sum--;
35         sg_update(now);
36         return ans;
37     }
38     int mid=(a[now].l+a[now].r)>>1;
39     if(x<=mid)sg_delete(now<<1,x);
40     else sg_delete(now<<1|1,x);
41     a[now].sum--;
42     sg_update(now);
43     return ans;
44 }
45 void sg_add(int l,int r,int now,int x){
46     if(l<=a[now].l&&r>=a[now].r){
47         a[now].v.push_back(x);
48         bal[x]=r-l+1;
49         return;
50     }
51     int mid=(a[now].l+a[now].r)>>1;
52     if(l<=mid)sg_add(l,r,now<<1,x);
53     if(mid<r)sg_add(l,r,now<<1|1,x);
54 
55 }
56 int main(){
57 //  freopen("c.in","r",stdin);
58     scanf("%d%d",&n,&m);
59     for(int i=1;i<=n;i++)
60         scanf("%d",&f[i]);
61     sg_build(1,n,1);
62     for(int i=1;i<=m;i++)
63         scanf("%d%d",&l,&r),
64         sg_add(l,r,1,i);
65     scanf("%d",&q);
66     for(int i=1;i<=q;i++)
67         scanf("%d",&x),
68         lastans=sg_delete(1,(x+lastans-1)%n+1),
69         printf("%d\n",ans);
70     return 0;
71 }

 

posted @ 2017-08-11 16:16  skylynf  阅读(423)  评论(1编辑  收藏  举报