CF1539F 题解

CF1539F

思路

中位数相关,考虑 \(a_j>a_i\)\(j\) 设为 \(1\)\(a_j<a_i\)\(j\) 设为 \(-1\),做前缀和。问题是 \(a_j=a_i\) 时可以任意排列。

  • \(a_i>a_{mid}\)\(a_j=a_i\)\(j\) 放在 \(i\) 前,设为 \(-1\)。此时 \(-1\) 数量多于 \(1\)\(ans=\max \sum [a_j\leq a_i] -\lceil \frac{l+r}{2} \rceil=\frac{-\min (sum_r-sum_{l-1})-1}{2}\)

  • 否则,\(a_j=a_i\)\(j\) 放在 \(i\) 后,设为 \(1\)。此时 \(1\) 数量多于 \(-1\)\(ans=\max \sum [a_j\geq a_i] -\lceil \frac{l+r}{2} \rceil=\frac{\max (sum_r-sum_{l-1})}{2}\)

具体系数可以带入数推。现在要动态维护 \(\max (sum_r-sum_{l-1})\)。可以按 \(a_i\) 从小往大加入。初始时 \(sum_i=i\),当 \(a_i\) 改为 \(-1\) 时,线段树维护区间 \([i,n]\)\(2\)\(\max (sum_r-sum_{l-1})=\max_{j=i}^{n}sum_j-\min_{j=1}^{i}sum_{j-1}\)。查询区间最值。min 同理。

code

int n,a[maxn];
struct sgt{
#define mid (l+r>>1)
#define ls nd<<1
#define rs nd<<1|1
	int mn[maxn<<2],mx[maxn<<2],tag[maxn<<2];
	void push(int nd){
		mn[ls]+=tag[nd],mx[ls]+=tag[nd],tag[ls]+=tag[nd];
		mn[rs]+=tag[nd],mx[rs]+=tag[nd],tag[rs]+=tag[nd];
		tag[nd]=0;
	}
	void updata(int nd,int l,int r,int ql,int qr,int w){
		if(l>=ql&&r<=qr){
			mn[nd]+=w,mx[nd]+=w,tag[nd]+=w;
			return ;
		}
		if(tag[nd])push(nd);
		if(ql<=mid)updata(ls,l,mid,ql,qr,w);
		if(qr>mid)updata(rs,mid+1,r,ql,qr,w);
		mn[nd]=min(mn[ls],mn[rs]),mx[nd]=max(mx[ls],mx[rs]);
	}
	int qmn(int nd,int l,int r,int ql,int qr){
		if(l>=ql&&r<=qr)return mn[nd];
		if(tag[nd])push(nd);
		if(qr<=mid)return qmn(ls,l,mid,ql,qr);
		if(ql>mid)return qmn(rs,mid+1,r,ql,qr);
		return min(qmn(ls,l,mid,ql,qr),qmn(rs,mid+1,r,ql,qr));
	}
	int qmx(int nd,int l,int r,int ql,int qr){
		if(l>=ql&&r<=qr)return mx[nd];
		if(tag[nd])push(nd);
		if(qr<=mid)return qmx(ls,l,mid,ql,qr);
		if(ql>mid)return qmx(rs,mid+1,r,ql,qr);
		return max(qmx(ls,l,mid,ql,qr),qmx(rs,mid+1,r,ql,qr));
	}
}s;
vector<int> pos[maxn];	
int ans[maxn];
void work(){
	n=read();
	for(int i=1;i<=n;i++){
		a[i]=read(),pos[a[i]].push_back(i);
		s.updata(1,0,n,i,n,1);
	}
	for(int i=1;i<=n;i++)if(pos[i].size()){
		for(int j:pos[i]){
//			cout<<j<<" "<<s.qmx(1,0,n,j,n)-s.qmn(1,0,n,0,j-1)<<" ";
			ans[j]=max(ans[j],(s.qmx(1,0,n,j,n)-s.qmn(1,0,n,0,j-1))/2);
		}
		for(int j:pos[i])s.updata(1,0,n,j,n,-2);
		for(int j:pos[i]){
//			cout<<j<<" "<<-(s.qmn(1,0,n,j,n)-s.qmx(1,0,n,0,j-1))<<"\n";
			ans[j]=max(ans[j],(-(s.qmn(1,0,n,j,n)-s.qmx(1,0,n,0,j-1))-1)/2);
		}
	}
	for(int i=1;i<=n;i++)printf("%lld ",ans[i]);
}
posted @ 2024-05-10 19:58  yhddd  阅读(5)  评论(0编辑  收藏  举报