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]);
}