Seeds bear new life when flowers dare to fade
非常新鲜,非常美味
先想点怎么进行 \(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;
}

浙公网安备 33010602011771号