Luogu5324 BJOI2019删数(线段树)
Posted gloid
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Luogu5324 BJOI2019删数(线段树)相关的知识,希望对你有一定的参考价值。
考虑无修改怎么做。对于1~n的每个数,若其存在,将最后一个放在其值的位置,剩余在其前面依次排列,答案即为值域1~n上没有数的位置个数。带修改显然记一下偏移量线段树改一改就好了。
#include<iostream> #include<cstdio> #include<cmath> #include<cstdlib> #include<cstring> #include<algorithm> using namespace std; #define ll long long #define N 600010 char getc(){char c=getchar();while ((c<‘A‘||c>‘Z‘)&&(c<‘a‘||c>‘z‘)&&(c<‘0‘||c>‘9‘)) c=getchar();return c;} int gcd(int n,int m){return m==0?n:gcd(m,n%m);} int read() { int x=0,f=1;char c=getchar(); while (c<‘0‘||c>‘9‘) {if (c==‘-‘) f=-1;c=getchar();} while (c>=‘0‘&&c<=‘9‘) x=(x<<1)+(x<<3)+(c^48),c=getchar(); return x*f; } int n,m,V,L[N<<2],R[N<<2],tree[N<<2][2],lazy[N<<2],a[N],cnt[N],delta; void up(int k) { tree[k][0]=min(tree[k<<1][0],tree[k<<1|1][0]); tree[k][1]=0; if (tree[k<<1][0]==tree[k][0]) tree[k][1]+=tree[k<<1][1]; if (tree[k<<1|1][0]==tree[k][0]) tree[k][1]+=tree[k<<1|1][1]; } void build(int k,int l,int r) { L[k]=l,R[k]=r; if (l==r) {tree[k][0]=0;tree[k][1]=1;return;} int mid=l+(r-l)/2; build(k<<1,l,mid); build(k<<1|1,mid+1,r); up(k); } void update(int k,int x){tree[k][0]+=x,lazy[k]+=x;} void down(int k){update(k<<1,lazy[k]),update(k<<1|1,lazy[k]),lazy[k]=0;} void add(int k,int l,int r,int x) { if (L[k]==l&&R[k]==r) {update(k,x);return;} if (lazy[k]) down(k); int mid=L[k]+(R[k]-L[k])/2; if (r<=mid) add(k<<1,l,r,x); else if (l>mid) add(k<<1|1,l,r,x); else add(k<<1,l,mid,x),add(k<<1|1,mid+1,r,x); up(k); } int query(int k,int l,int r) { if (L[k]==l&&R[k]==r) {return tree[k][1]*(tree[k][0]==0);} if (lazy[k]) down(k); int mid=L[k]+(R[k]-L[k])/2; if (r<=mid) return query(k<<1,l,r); else if (l>mid) return query(k<<1|1,l,r); else return query(k<<1,l,mid)+query(k<<1|1,mid+1,r); } int main() { #ifndef ONLINE_JUDGE freopen("a.in","r",stdin); freopen("a.out","w",stdout); const char LL[]="%I64d\n"; #else const char LL[]="%lld\n"; #endif n=read(),m=read();V=max(n,m)<<1; for (int i=1;i<=n;i++) a[i]=read(); build(1,-V,V); for (int i=1;i<=n;i++) cnt[a[i]+V]++; for (int i=1;i<=n;i++) if (cnt[i+V]) add(1,i-cnt[i+V]+1,i,1); for (int i=1;i<=m;i++) { int p=read(),x=read(); if (p==0) { if (x==-1) { if (cnt[1-delta+V]) add(1,2-cnt[1-delta+V]-delta,1-delta,-1); delta--; if (cnt[n-delta+V]) add(1,n-cnt[n-delta+V]-delta+1,n-delta,1); } else { if (cnt[n-delta+V]) add(1,n-cnt[n-delta+V]-delta+1,n-delta,-1); delta++; if (cnt[1-delta+V]) add(1,2-cnt[1-delta+V]-delta,1-delta,1); } } else { --cnt[a[p]+V]; if (a[p]+delta>=1&&a[p]+delta<=n) add(1,a[p]-cnt[a[p]+V],a[p]-cnt[a[p]+V],-1); a[p]=x-delta; if (a[p]+delta>=1&&a[p]+delta<=n) add(1,a[p]-cnt[a[p]+V],a[p]-cnt[a[p]+V],1); cnt[a[p]+V]++; } printf("%d\n",query(1,1-delta,n-delta)); } return 0; }
以上是关于Luogu5324 BJOI2019删数(线段树)的主要内容,如果未能解决你的问题,请参考以下文章