*题解:CF2229D Me When Median Problem

题目链接

解析

首先,由于操作始终会使 \(a\) 的某两个位置被 \(s_2\) 替换且 \(s_2\le s_3\),所以当 \(n > 1\) 时,最终的答案 \(\min(a_1,b_1)=a_1\)

考虑二分答案 \(x\),这样 \(a,b\) 中大于等于 \(x\) 的数本质相同, 小于等于 \(x\) 的数也本质相同,所以不妨将其分别设为 \(1\)\(0\)。这样,问题转化为在 0 / 1 序列上求解。

先一位一位考虑,发现只有当 \(a_i=1\)\(b_i=1\) 时,对 \(i\)\(i - 1\) 进行操作后才有可能使最终的 \(s_2,s_3\) 不含 \(0\)。对于 \(i\) 左边的不存在 \(a_j=1\)\(b_j=1\) 的极长连续段,对其充分进行操作,最后剩下的 \(a,b\) 中必定有 \(1\) 个或 \(2\) 个为 \(0\)。二者区别在于是否存在 \(a_j=b_j=0\)

定义两个多集 \(\{a,b\},\{c,d\}\) 之间进行配对操作的结果为对 \(S=\{a,b,c,d\}\) 进行操作后 \(s_2,s_3\) 组成的多集 \(\{s_2,s_3\}\)。对于剩下 \(\{0,1\}\) 的情况,直接配对就可以把这个 \(0\) 抹除,得到 \(\{1,1\}\)。否则操作后会变为 \(\{0,1\}\),还需要跟一个 \(\{1,1\}\) 配对才能把 \(0\) 抹除。由于 \(\{0,1\}\)\(\{0,1\}\) 配对还是 \(\{0,1\}\),所以可以把所有 \(\{0,1\}\) 配对完之后再跟一个 \(\{1,1\}\) 配对。这样,需要 \(\{1,1\}\) 的个数为不存在 \(a_i=b_i=1\) 且存在 \(a_i=b_i=0\) 的极长连续段个数加 \(1\)

时间复杂度 \(O(n \log n)\)

代码

/*
*/
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int N = 2e5 + 5,M = 10 + 5,L = 19,L2 = 17,mod = (int)1e9 + 7;
int a[N],b[N],c[N],d[N];
int n;
bool chk(int x){
	int cnt0 = 0,cnt1 = 0,pre = 1;
	for(int i=1;i<=n;i++){
		c[i] = a[i] >= x;
		d[i] = b[i] >= x;
		int cnt = c[i] + d[i];
		if(cnt == 0){
			if(pre != 0){
				cnt0++;	
				pre = 0;
			}
		}else if(cnt == 2){
			pre = 1;
			cnt1++;
		}
	}
	return cnt1 > cnt0;
}
signed main(){
	ios::sync_with_stdio(false);
	cin.tie(0),cout.tie(0);
//	freopen("in.txt","r",stdin);
//	freopen("out.txt","w",stdout);
	int T;
	cin>>T;
	while(T--){
		cin>>n;
		for(int i=1;i<=n;i++){
			cin>>a[i];
		}
		for(int i=1;i<=n;i++){
			cin>>b[i];
		}
		int l = 1,r = 2 * n;
		while(l < r){
			int mid = (l + r + 1) >> 1;
			if(chk(mid)){
				l = mid;
			}else{
				r = mid - 1;
			}
		}
		cout<<l<<'\n';
	}
	return 0;
}

posted @ 2026-05-26 02:44  yutar  阅读(16)  评论(0)    收藏  举报