• 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
    ";
    #else
    	const char LL[]="%lld
    ";
    #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
    ",query(1,1-delta,n-delta));
    	}
    	return 0;
    }
    

      

  • 相关阅读:
    多线程中注意事项
    多线程实现第三种方式
    线程池《一》
    线程组
    线程间通信注意的问题
    互斥锁
    多个线程通信的问题
    二个线程间的通信
    死锁产生的原理
    线程安全问题
  • 原文地址:https://www.cnblogs.com/Gloid/p/10795494.html
Copyright © 2020-2023  润新知