「杂题乱刷2」CF2085F2
感谢 @incra 的讲解。
题目链接
解题思路
考虑 F1 做法,发现直接枚举每个数作为中心点即可,只需要维护距离中心点的其余值的最小位置,时间复杂度 \(O(n^2)\)。
然后你可以注意到中心点不一定是中心点,具体的,左右两边数字不一定是平均的,由于这种情况一定是不优的,所以不用去管。
那么你发现剩下的可以直接使用二维差分对原来的暴力做优化,做完了。
注意需要分讨一下区间不同的奇偶情况。
时间复杂度 \(O(n)\)。
参考代码
ll n,m;
ll a[1000010],ans[1000010];
ll lst[1000010],now[1000010];
void upd(ll l,ll r,ll x)
{
if(l<=r)
ans[l]+=x,
ans[r+1]-=x;
}
void _clear(){}
void solve()
{
_clear();
cin>>n>>m;
forl(i,1,m)
lst[i]=now[i]=0;
forl(i,1,n)
ans[i]=0;
forl(i,1,n)
cin>>a[i],
lst[a[i]]=i;
forl(i,1,n)
{
if(i==lst[a[i]])
upd(i+1,n,1);
if(!now[a[i]])
upd(1,1,i-1),
upd(2,i,-1);
else
{
ll l=now[a[i]],r=i;
ll Mid=(l+r+1)/2;
if((l+r)%2==0)
upd(l+1,Mid,1),
upd(Mid+1,r,-1);
else
upd(l+1,Mid-1,1),
upd(Mid+1,r,-1);
}
now[a[i]]=i;
}
forl(i,1,n)
ans[i]+=ans[i-1];
forl(i,1,n)
ans[i]+=ans[i-1];
ll A=1e18;
forl(i,1,n)
Min(A,ans[i]);
forl(i,1,m)
A-=abs((m+1)/2-i);
cout<<A<<endl;
}

浙公网安备 33010602011771号