• [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
    ",que(1,1,mx,py+1,py+n));
    74     }
    75     return 0;
    76 }
  • 相关阅读:
    C语言之分支语句
    C语言之运算符与表达式
    C语言之数据类型④——中文字符
    独特的对象引用:this
    理解赋值“=”的含义
    编写类的 “模板”
    类的定义
    Java语言规范
    第一周总结
    定义常量
  • 原文地址:https://www.cnblogs.com/HocRiser/p/10799344.html
Copyright © 2020-2023  润新知