[Luogu5324][BJOI2019]删数(线段树)

CF风格题,先猜结论,记数列中i这个数共出现了cnt[i]次,那么所有区间[i-cnt[i]+1,i]的并集的补集大小就是答案。

于是我们只需要线段树维护每个位置是否被某个区间覆盖到即可,对于整体加减操作,设一个偏移量即可。

 1 #include<cstdio>
 2 #include<algorithm>
 3 #define ls (x<<1)
 4 #define rs (ls|1)
 5 #define lson ls,L,mid
 6 #define rson rs,mid+1,R
 7 #define rep(i,l,r) for (int i=(l); i<=(r); i++)
 8 using namespace std;
 9 
10 const int N=600010;
11 int n,m,mx,py,L,p,x,a[N],num[N],v[N<<2],c[N<<2],mn[N<<2],tag[N<<2];
12 
13 void upd(int x){
14     if (mn[ls]<mn[rs]) mn[x]=mn[ls],c[x]=c[ls];
15     else if (mn[ls]>mn[rs]) mn[x]=mn[rs],c[x]=c[rs];
16         else mn[x]=mn[ls],c[x]=c[ls]+c[rs];
17     if (!mn[x]) v[x]=c[x]; else v[x]=0;
18 }
19 
20 void put(int x,int k){
21     mn[x]+=k; tag[x]+=k;
22     if (!mn[x]) v[x]=c[x]; else v[x]=0;
23 }
24 
25 void push(int x){
26     if (!tag[x]) return;
27     put(ls,tag[x]); put(rs,tag[x]); tag[x]=0;
28 }
29 
30 void build(int x,int L,int R){
31     if (L==R){ c[x]=v[x]=1; return; }
32     int mid=(L+R)>>1;
33     build(lson); build(rson); upd(x);
34 }
35 
36 void mdf(int x,int L,int R,int l,int r,int k){
37     if (L==l && r==R){ put(x,k); return; }
38     int mid=(L+R)>>1; push(x);
39     if (r<=mid) mdf(lson,l,r,k);
40     else if (l>mid) mdf(rson,l,r,k);
41         else mdf(lson,l,mid,k),mdf(rson,mid+1,r,k);
42     upd(x);
43 }
44 
45 int que(int x,int L,int R,int l,int r){
46     if (L==l && r==R) return v[x];
47     int mid=(L+R)>>1; push(x);
48     if (r<=mid) return que(lson,l,r);
49     else if (l>mid) return que(rson,l,r);
50         else return que(lson,l,mid)+que(rson,mid+1,r);
51 }
52 
53 void Mdf(int x,int w){
54     int k=num[py+x]+(w>0); num[py+x]+=w;
55     if (x<=n) mdf(1,1,mx,py+x-k+1,py+x-k+1,w);
56 }
57 
58 int main(){
59     freopen("number.in","r",stdin);
60     freopen("number.out","w",stdout);
61     scanf("%d%d",&n,&m); mx=(n+m)*2+1; py=n+m; build(1,1,mx);
62     rep(i,1,n) scanf("%d",&a[i]),Mdf(a[i],1);
63     while (m--){
64         scanf("%d%d",&p,&x);
65         if (p>0) Mdf(a[p]+L,-1),a[p]=x-L,Mdf(a[p]+L,1);
66         else if (x>0){
67             py--; L++; int pos=py+n+1;
68             if (num[pos]>0) mdf(1,1,mx,pos-num[pos]+1,pos,-1);
69         }else{
70             int pos=py+n+1; py++; L--;
71             if (num[pos]>0) mdf(1,1,mx,pos-num[pos]+1,pos,1);
72         }
73         printf("%d\n",que(1,1,mx,py+1,py+n));
74     }
75     return 0;
76 }

 

posted @ 2019-05-01 10:46  HocRiser  阅读(130)  评论(0编辑  收藏  举报