CodeForces 1558F Strange Sort

题目传送门

首先我们考虑将原问题缩小值域,即将原序列变为 \(01\) 序列。那么现在问题变成了在 \(01\) 序列上怎么做,以及怎么转化成 \(01\) 序列。

首先我们设定一个阈值 \(k\),令所有小于 \(k\) 的数变为 \(0\),其它数变为 \(1\)。对于所有的 \(k\) 求出的最大交换次数即为原问题的答案。

考虑如果我们有一个固定的 \(01\) 序列,应该怎么求解,显然我们可以 dp。

首先我们假设序列中有 \(m\)\(0\)。那么我们还可以注意到,后面的 \(0\) 一定比前面的更晚归位。

于是我们设 \(f_i\) 表示第 \(i\)\(0\) 归位需要几步。显然有 \(f_i\leftarrow \max(f_{i-1}+1,(k_i+(p_i\bmod 2)))\)

于是有 \(f_m\leftarrow \displaystyle\max_{i=t}^{m}(k_i+(p_i\bmod 2)+m-i)\)

我们现在相当于要动态把一个序列中的 \(1\) 改为 \(0\),然后维护上面的式子,直接是用线段树即可。

#include<bits/stdc++.h>
#define int long long
#define N 200005
#define pii pair<int,int>
#define x first
#define y second
#define pct __builtin_popcount
#define mod 998244353
using namespace std;
int T=1,n,a[N],p[N],inf=2e9;
struct sgt{
	int tr[N<<2],s[N<<2],s1[N<<2],lzy[N<<2];
	void pushup(int u){
		tr[u]=max(tr[u<<1],tr[u<<1|1]);
		s[u]=s[u<<1]+s[u<<1|1];
		s1[u]=s1[u<<1]+s1[u<<1|1];
	}
	void build(int u,int l,int r){
		lzy[u]=0;
		if(l==r){
			tr[u]=0;
			s[u]=1;
			s1[u]=1;
			return;
		}
		int mid=l+r>>1;
		build(u<<1,l,mid);
		build(u<<1|1,mid+1,r);
		pushup(u);
	}
	void maketag(int u,int v){
		tr[u]+=v;
		lzy[u]+=v;
	}
	void pushdown(int u){
		maketag(u<<1,lzy[u]);
		maketag(u<<1|1,lzy[u]);
		lzy[u]=0;
	}
	void modify1(int u,int l,int r,int L,int R,int v){
		if(L>R)return;
		if(l>=L&&r<=R){
			maketag(u,v);
			return;
		}
		int mid=l+r>>1;
		pushdown(u);
		if(L<=mid)modify1(u<<1,l,mid,L,R,v);
		if(R>mid)modify1(u<<1|1,mid+1,r,L,R,v);
		pushup(u);
	}
	void modify(int u,int l,int r,int p){
		if(l==r){
			tr[u]=0;
			s1[u]--;
			return;
		}
		int mid=l+r>>1;
		pushdown(u);
		if(p<=mid)modify(u<<1,l,mid,p);
		else modify(u<<1|1,mid+1,r,p);
		pushup(u);
	}
	int qryp(int u,int l,int r){
		if(l==r&&s1[u]==0)return n+1;
		if(l==r)return l;
		int mid=l+r>>1;
		pushdown(u);
		if(s1[u<<1]!=0)return qryp(u<<1,l,mid);
		else return qryp(u<<1|1,mid+1,r);
	}
	int qry1(int u,int l,int r,int L,int R){
		if(L>R)return 0;
		if(l>=L&&r<=R)return s1[u];
		int mid=l+r>>1;
		int res=0;
		pushdown(u);
		if(L<=mid)res+=qry1(u<<1,l,mid,L,R);
		if(R>mid)res+=qry1(u<<1|1,mid+1,r,L,R);
		return res;
	}
	int qry(int u,int l,int r,int L,int R){
		if(L>R)return 0;
		if(l>=L&&r<=R)return tr[u];
		int mid=l+r>>1;
		int res=0;
		pushdown(u);
		if(L<=mid)res=max(res,qry(u<<1,l,mid,L,R));
		if(R>mid)res=max(res,qry(u<<1|1,mid+1,r,L,R));
		return res;
	}
}s;
void solve(int cs){
	cin>>n;
	for(int i=1;i<=n;i++){
		cin>>a[i];
		p[a[i]]=i;
	}
	s.build(1,1,n);
	int res=0;
	for(int k=1;k<=n;k++){
		int i=p[k];
		s.modify(1,1,n,i);
		s.modify1(1,1,n,1,i-1,1);
		s.modify1(1,1,n,i+1,n,-1);
		s.modify1(1,1,n,i,i,s.qry1(1,1,n,1,i-1)+(i%2)+(n-s.qry1(1,1,n,1,n)-i+s.qry1(1,1,n,1,i)));
		int pos=s.qryp(1,1,n);
		res=max(res,s.qry(1,1,n,pos,n));
	}
	cout<<res<<'\n';
}
signed main(){
	ios::sync_with_stdio(0);
	cin.tie(0);cout.tie(0);
	cin>>T;
//	init();
	for(int cs=1;cs<=T;cs++){
		solve(cs);
	}
	return 0;
}
posted @ 2025-03-30 17:56  zxh923  阅读(20)  评论(0)    收藏  举报