「杂题乱刷2」CF2085F2

感谢 @incra 的讲解。

题目链接

CF2085F2 *2900

解题思路

考虑 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;
}
posted @ 2025-04-09 15:20  wangmarui  阅读(12)  评论(0)    收藏  举报