Seeds bear new life when flowers dare to fade

非常新鲜,非常美味

QOJ 19025

先想点怎么进行 \(O(n)\) 的判定。显然的,只有 \(k\) 成为中位数时,我们才能够完成。

再考虑怎么求最小次数。不难发现一次操作会减少 1 个或 2 个不为 \(k\) 的点,那么问题等价于我们希望单次 \(-2\) 尽可能多。

然后发现,这个能够发生,当且仅当 \(k\) 是中位数并且满足其余的点都不为 \(k\)。因此,我们不妨记录 \(=k\) 的为 0,\(>k\) 的为 1,\(<k\) 的为 -1,我们不妨考虑对于距离 \(\le 2\) 的 \(1\) 和 \(-1\) 进行连边,那么问题等价于求最大匹配数。

考虑优化这个东西,考虑直接上线段树,然后维护匹配就行了。具体的考虑下,也就是先删掉 \(=0\) 的点,然后用线段树进行维护,如果有相邻的 \(0\) 就必须结算前一段。

Code

#include<bits/stdc++.h>
using namespace std;
#define IOS ios::sync_with_stdio(false);cin.tie(0),cout.tie(0)
#define File(s) freopen(s".in","r",stdin);freopen(s".out","w",stdout)
#define LL long long
#define fi first
#define se second
const int N = 2e5 + 10;
int n,Q;
int ans[N],a[N];
vector<int> vec[N];
struct node{
	int lval,rval;
	int lid,rid;
	int dp[2][2];
	int cnt;
	node(){
		lval = rval = lid = rid = cnt = 0;
		memset(dp,0,sizeof dp);
	}
	node operator + (const node &b) const{
		node res;
		if(cnt == 0) return b;
		if(b.cnt == 0) return (*this);
		res.lid = lid;
		res.rid = b.rid;
		res.lval = lval;
		res.rval = b.rval;
		res.cnt = cnt + b.cnt;
		if(cnt == 1 && b.cnt == 1){
			res.dp[0][0] = 0;
			if(rval + b.lval == 0 && b.lid - rid <= 2) res.dp[1][1] = 1;
			else res.dp[1][1] = 0;
			res.dp[0][1] = 0;
			res.dp[1][0] = 0;
		}
		else if(cnt == 1){
			for(int i=0;i<2;i++)
				for(int j=0;j<2;j++){
					res.dp[0][j] = max(res.dp[0][j],b.dp[i][j]);
					if(i == 0 && rval + b.lval == 0 && b.lid - rid <= 2)
						res.dp[1][j] = max(res.dp[1][j],b.dp[i][j] + 1);
					res.dp[1][j] = max(res.dp[1][j],b.dp[i][j]);
				}
		}
		else if(b.cnt == 1){
			for(int i=0;i<2;i++)
				for(int j=0;j<2;j++){
					res.dp[i][0] = max(res.dp[i][0],dp[i][j]);
					if(j == 0 && rval + b.lval == 0 && b.lid - rid <= 2)
						res.dp[i][1] = max(res.dp[i][1],dp[i][j] + 1);
					res.dp[i][1] = max(res.dp[i][1],dp[i][j]);
				}
		}
		else{
			for(int i=0;i<2;i++){
				for(int j=0;j<2;j++)
					for(int k=0;k<2;k++){
						for(int l=0;l<2;l++){
							res.dp[i][l] = max(res.dp[i][l],dp[i][j] + b.dp[k][l]);
							if(j == 0 && k == 0 && b.lid - rid <= 2 && rval + b.lval == 0)
								res.dp[i][l] = max(res.dp[i][l],dp[i][j] + b.dp[k][l] + 1);
						}
					}
			}
		}
		return res;
	}
};
struct segment_tree{
	node tre[N << 2];
	void pushup(int p){
		tre[p] = tre[p*2] + tre[p*2+1];
	}
	void build(int pl,int pr,int p){
		if(pl == pr){
			tre[p].lid = tre[p].rid = pl;
			tre[p].lval = tre[p].rval = 1;
			memset(tre[p].dp,0,sizeof tre[p].dp);
			tre[p].cnt = 1;
			return ;
		}
		int mid = pl + pr >> 1;
		build(pl,mid,p*2);
		build(mid+1,pr,p*2+1);
		pushup(p);
	}
	void update(int x,int pl,int pr,int p,int val){
		if(pl == pr){
			if(val == 0){
				tre[p].cnt = 0;
			}
			else{
				tre[p].cnt = 1;
				tre[p].lval = tre[p].rval = val;
				tre[p].lid = tre[p].rid = pl;
			}
			return ;
		}
		int mid = pl + pr >> 1;
		if(x <= mid) update(x,pl,mid,p*2,val);
		else update(x,mid+1,pr,p*2+1,val);
		pushup(p);
		return ;
	}
	node query(int L,int R,int pl,int pr,int p){
		if(pl > pr || L > R || pl > R || pr < L)
			return node();
		int mid = pl + pr >> 1;
		if(L <= pl && pr <= R)
			return tre[p];
		return query(L,R,pl,mid,p*2) + query(L,R,mid+1,pr,p*2+1);
	}
}sgt;
int lsh[N];
unordered_map<int,int> mp;
void solve(){
	cin >> n >> Q;
	mp.clear();
	for(int i=1;i<=n;i++){
		cin >> a[i];
		lsh[i] = a[i];
	}
	for(int i=1;i<=n;i++){
		if(i > 1 && a[i] >= a[i-1] && i < n && a[i] <= a[i+1]) mp[a[i]] = 1;
		if(i > 1 && a[i] >= a[i-1] && i > 2 && a[i] <= a[i-2]) mp[a[i]] = 1;
		if(i < n && a[i] >= a[i+1] && i + 1 < n && a[i] <= a[i+2]) mp[a[i]] = 1;

		if(i > 1 && a[i] <= a[i-1] && i < n && a[i] >= a[i+1]) mp[a[i]] = 1;
		if(i > 1 && a[i] <= a[i-1] && i > 2 && a[i] >= a[i-2]) mp[a[i]] = 1;
		if(i < n && a[i] <= a[i+1] && i + 1 < n && a[i] >= a[i+2]) mp[a[i]] = 1;
	}
	sgt.build(1,n,1);
	sort(lsh+1,lsh+1+n);
	int len = unique(lsh+1,lsh+1+n) - lsh - 1;
	for(int i=1;i<=n;i++){
		a[i] = lower_bound(lsh+1,lsh+1+len,a[i]) - lsh;
		vec[a[i]].push_back(i);
		// cout << a[i] << " ";
	}
	for(int i=1;i<=len;i++){
		ans[i] = 0;
		for(int id : vec[i])
			sgt.update(id,1,n,1,0);
		int L = 1;
		for(int j=1;j<vec[i].size();j++){
			int pre = vec[i][j-1],nw = vec[i][j];
			if(pre == nw - 1){
				if(L == nw) L ++ ;
				else{
					node res = sgt.query(L,pre-1,1,n,1);
					int mx = max(res.dp[0][0],res.dp[0][1]);
					mx = max(mx,max(res.dp[1][0],res.dp[1][1]));
					ans[i] += mx;
					L = nw + 1;
				}
			}
		}
		if(L <= n){
			node res = sgt.query(L,n,1,n,1);
			int mx = max(res.dp[0][0],res.dp[0][1]);
			mx = max(mx,max(res.dp[1][0],res.dp[1][1]));
			ans[i] += mx;
		}
		for(int id : vec[i])
			sgt.update(id,1,n,1,-1);
		ans[i] = n - (int)vec[i].size() - ans[i];
		vec[i].clear();
	}
	while(Q -- ){
		int k;
		cin >> k;
		if(mp.count(k)){
			k = lower_bound(lsh+1,lsh+1+len,k) - lsh;
			cout << ans[k] << "\n";
		}
		else
			cout << -1 << "\n";
	}
}
int main(){
	IOS;
	int T;
	cin >> T;
	while(T -- )
		solve();
	return 0;
}
posted @ 2026-09-20 21:11  WinterXorSnow  阅读(12)  评论(0)    收藏  举报