码迷,mamicode.com
首页 > 其他好文 > 详细

Luogu5324 BJOI2019删数(线段树)

时间:2019-04-30 14:13:23      阅读:153      评论:0      收藏:0      [点我收藏+]

标签:排列   char   getchar   div   个数   add   fine   getch   include   

  考虑无修改怎么做。对于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删数(线段树)

标签:排列   char   getchar   div   个数   add   fine   getch   include   

原文地址:https://www.cnblogs.com/Gloid/p/10795494.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!