Live2D

[BJOI2019]删数 题解

link

Solution

虽然要AFO了,但是不妨记录一下最后的日子。/kk

首先可以看出,合法条件就是对于存在的 \(x\),那么 \(\le x\) 的数的个数恰好等于 \(x\),那么我们可以转化一下,相当于对于一个位置 \(i\) 存在 \(x\) 个,那么我们覆盖 \([i-x+1,i]\),如果恰好覆盖了 \([1,n]\),那么就是合法的。考虑最小修改次数,显然就是没有被覆盖到的点数,这玩意可以维护区间最小值及其个数。

注意到单点修改容易操作,考虑整体加减 \(1\),可以发现我们可以通过标记实现。

Code

#include <bits/stdc++.h>
using namespace std;

#define Int register int
#define MAXN 450005

template <typename T> inline void read (T &t){t = 0;char c = getchar();int f = 1;while (c < '0' || c > '9'){if (c == '-') f = -f;c = getchar();}while (c >= '0' && c <= '9'){t = (t << 3) + (t << 1) + c - '0';c = getchar();} t *= f;}
template <typename T,typename ... Args> inline void read (T &t,Args&... args){read (t);read (args...);}
template <typename T> inline void write (T x){if (x < 0){x = -x;putchar ('-');}if (x > 9) write (x / 10);putchar (x % 10 + '0');}
template <typename T> inline void chkmax (T &a,T b){a = max (a,b);}
template <typename T> inline void chkmin (T &a,T b){a = min (a,b);}

int n,m,a[MAXN],up,st;

struct node{
	int miv,sum;
	node operator + (const node &p)const{
		if (miv < p.miv) return *this;
		else if (miv == p.miv) return node{miv,sum + p.sum};
		else return p;
	}
};

struct Segment{
	node Sum[MAXN << 2];int tag[MAXN << 2];
	void pushadd (int x,int v){Sum[x].miv += v,tag[x] += v;}
	void pushdown (int x){pushadd (x << 1,tag[x]),pushadd (x << 1 | 1,tag[x]),tag[x] = 0;}
	void pushup (int x){Sum[x] = Sum[x << 1] + Sum[x << 1 | 1];}
	void modify (int x,int l,int r,int ql,int qr,int v){
		if (l >= ql && r <= qr) return pushadd (x,v);
		int mid = l + r >> 1;pushdown (x);
		if (ql <= mid) modify (x << 1,l,mid,ql,qr,v);
		if (qr > mid) modify (x << 1 | 1,mid + 1,r,ql,qr,v);
		pushup (x);
	}
	void build (int x,int l,int r){
		Sum[x] = node{0,r - l + 1};
		if (l == r) return ;
		int mid = l + r >> 1;
		build (x << 1,l,mid),build (x << 1 | 1,mid + 1,r);
	}
	int query (int x,int l,int r,int ql,int qr){
		if (l >= ql && r <= qr) return Sum[x].miv == 0 ? Sum[x].sum : 0;
		int mid = l + r >> 1,res = 0;pushdown (x);
		if (ql <= mid) res += query (x << 1,l,mid,ql,qr);
		if (qr > mid) res += query (x << 1 | 1,mid + 1,r,ql,qr);
		return res;
	}
}tree;

int b[MAXN];
void change (int x,int c){
	int pos = x - b[x] + 1 - (c > 0);
	tree.modify (1,1,up,pos,pos,c),b[x] += c; 
}

signed main(){
	read (n,m),up = 4.5e5 + 1,st = 1.5e5 + 1,tree.build (1,1,up);
	for (Int i = 1;i <= n;++ i) read (a[i]),a[i] += st,change (a[i],1);
	while (m --> 0){
		int p,x;read (p,x);
		if (p){
			if (a[p] <= st + n) change (a[p],-1);
			else b[a[p]] --;
			a[p] = st + x;
			if (a[p] <= st + n) change (a[p],1);
			else b[a[p]] ++;
		}
		else{
			if (x == 1 && b[st + n]) tree.modify (1,1,up,st + n - b[st + n] + 1,st + n,-1);
			st -= x;
			if (x == -1 && b[st + n]) tree.modify (1,1,up,st + n - b[st + n] + 1,st + n,1);  
		}
		write (tree.query (1,1,up,st + 1,st + n)),putchar ('\n');
	}
	return 0;
}
posted @ 2022-04-13 21:43  Dark_Romance  阅读(35)  评论(0编辑  收藏  举报