题解:CF2085F2 Serval and Colorful Array (Hard Version)
思路
首先想到一个小结论:假如我们已经钦定好了最后要组成排列的所有数字,定义第 这下真读者自证不难了。
然后又发现了一个小结论:如果我们已经确定了
设
稍加整理,得到下式:
可以发现,如果
代码
#include<bits/stdc++.h>
using namespace std;
#define int long long
const int N=4e5+10,inf=1e11,sgl=-2e11,sgr=2e11;
int n,m;
int w[N],a[N],b[N],suma;
int lst[N],nxt[N];
int root;
struct segmenttree{
int pcnt;
struct node{
int ls,rs,siz,data;
}t[N<<5];
void push_up(int p){
t[p].data=t[t[p].ls].data+t[t[p].rs].data;
t[p].siz=t[t[p].ls].siz+t[t[p].rs].siz;
}
void modify(int l,int r,int x,int &p,int d){
if(!p){p=++pcnt;t[p].ls=t[p].rs=t[p].data=t[p].siz=0;}
if(l==r){
t[p].siz+=d;t[p].data+=d*x;return ;
}
int mid=l+r>>1;
if(mid>=x)modify(l,mid,x,t[p].ls,d);
else modify(mid+1,r,x,t[p].rs,d);
push_up(p);
}
int query(int l,int r,int p,int k){
if(!p)return 0;
if(l==r)return t[p].data/t[p].siz*k;
int ret=0,mid=l+r>>1;
if(t[t[p].ls].siz>=k)ret=query(l,mid,t[p].ls,k);
else ret=query(mid+1,r,t[p].rs,k-t[t[p].ls].siz)+t[t[p].ls].data;
return ret;
}
}s;
void push(int a,int b,int d){
s.modify(sgl,sgr,a+b,root,d);suma+=a*d;
}
int ans=inf;
int Galse(int l,int r){
if(l>r)return 0;
return (l+r)*(r-l+1)/2;
}
void solve(){
cin>>n>>m;
for(int i=1;i<=n;i++)nxt[i]=0;
for(int i=1;i<=m;i++)a[i]=b[i]=lst[i]=0;
suma=s.pcnt=root=0;
ans=inf;
for(int i=1;i<=n;i++){
cin>>w[i];
nxt[lst[w[i]]]=i;
lst[w[i]]=i;
}
for(int i=1;i<=n;i++)if(!nxt[i])nxt[i]=inf;
for(int i=1;i<=m;i++)a[i]=-inf;
for(int i=1;i<=n;i++)if(!b[w[i]])b[w[i]]=i;
for(int i=1;i<=m;i++)push(a[i],b[i],1);
int l=m/2,r=m-l;
for(int i=1;i<=n;i++){
push(a[w[i]],b[w[i]],-1);
a[w[i]]=b[w[i]];b[w[i]]=nxt[i];
push(a[w[i]],b[w[i]],1);
ans=min(ans,Galse(i-l+1,i)-Galse(i+1,i+r)-suma+s.query(sgl,sgr,root,r));
}
cout<<ans<<"\n";
}
signed main(){
ios::sync_with_stdio(false);cin.tie(0);
int T;cin>>T;
while(T--){
solve();
}
return 0;
}