首页 > 其他 > 详细

! BJOI2019删数

时间:2020-04-24 11:33:47      阅读:56      评论:0      收藏:0      [点我收藏+]

技术分享图片

nm150000

发现答案相当于是值为i的数放在i号柱子上,然后将柱子向左推倒,未覆盖的位数为答案

线段树下标表示位置i被覆盖了几次,维护lazy标记,最小值及其个数

整体+1,-1操作最巧妙

我们不移动值,直接移动值域,例-1向右移,于是要在线段树前面和后面都空出max(n,m)的位置(注,当前值域的左端点代表1,右端点代表n,其余的叶子节点相应加减)

思考:若是区间修改怎么办?

#include<bits/stdc++.h>
using namespace std;
inline int read(){
	int x=0,f=1;char c=getchar();
	while(!isdigit(c)){if(c==‘-‘)f=-1;c=getchar();}
	while(isdigit(c)){x=(x<<1)+(x<<3)+(c^48);c=getchar();}
	return f==1?x:-x;
}
const int N=5e5+4;
int n,m,nm,nl,nr;
int a[N],c[N],co[N<<2],lz[N<<2],mn[N<<2];
#define lc (p<<1)
#define rc (p<<1|1)
void build(int p,int l,int r){
	co[p]=r-l+1;
	if(l==r)return;
	int mid=l+r>>1;
	build(lc,l,mid);
	build(rc,mid+1,r);
}
inline void pushup(int p){
	mn[p]=min(mn[lc],mn[rc]);
	if(mn[lc]==mn[rc])co[p]=co[lc]+co[rc];
	else co[p]=(mn[lc]<mn[rc])?co[lc]:co[rc];
}
inline void pushdown(int p){
	if(!lz[p])return;
	mn[lc]+=lz[p];lz[lc]+=lz[p];
	mn[rc]+=lz[p];lz[rc]+=lz[p];
	lz[p]=0;
}
void modify(int p,int l,int r,int ql,int qr,int v){
	if(ql<=l&&r<=qr){
		mn[p]+=v;lz[p]+=v;
		return;
	}
	int mid=l+r>>1;
	pushdown(p);
	if(ql<=mid)modify(lc,l,mid,ql,qr,v);
	if(mid<qr)modify(rc,mid+1,r,ql,qr,v);
	pushup(p);
}
int query(int p,int l,int r,int ql,int qr){
	if(ql<=l&&r<=qr)return mn[p]?0:co[p];
	int mid=l+r>>1;
	pushdown(p);
	if(qr<=mid)return query(lc,l,mid,ql,qr);
	if(mid<ql)return query(rc,mid+1,r,ql,qr);
	return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);
}
int main(){
	n=read();m=read();nm=n+max(n,m)*2;
	nl=max(n,m)+1;nr=nl+n-1;
	for(int i=1;i<=n;i++){
		a[i]=read()+nl-1;
		c[a[i]]++;
	}	
	build(1,1,nm);
	for(int i=nl;i<=nr;i++)
		if(c[i])modify(1,1,nm,i-c[i]+1,i,1);
	for(int i=1,op,x;i<=m;++i){
		op=read();x=read();
		if(op){
			if(a[op]<=nr)modify(1,1,nm,a[op]-c[a[op]]+1,a[op]-c[a[op]]+1,-1);
			--c[a[op]];
			a[op]=x+nl-1;
			++c[a[op]];
			modify(1,1,nm,a[op]-c[a[op]]+1,a[op]-c[a[op]]+1,1);
		}
		else{
			if(x==1){
				if(c[nr])modify(1,1,nm,nr-c[nr]+1,nr,-1);
				--nl;--nr;
			}
			else{
				++nl;++nr;
				if(c[nr])modify(1,1,nm,nr-c[nr]+1,nr,1);
			}
		}
		cout<<query(1,1,nm,nl,nr)<<"\n";
	}
	return (0-0);
}

! BJOI2019删数

原文:https://www.cnblogs.com/aurora2004/p/12766145.html

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!