Codeforces Round 1096 (Div. 3)补题

D. Palindromex

知识点:思维

思路:要注意到几个点,每个 \([0,n-1]\) 之间的数都出现了两次,而且要找最大 \(mex\) 的话,序列一定会有 \(0\),有两种情况 \(0\) 作为奇数串的中心,或者 \(0\) 在一个序列的两边,以这两个点为中心的回文串,也就是说只需要找三个回文串,分别是以 两个 \(0\) 为中心的子串和以 两个 \(0\) 中心为中心的子串,取其中的最大值即可

Code
点击查看代码
int f(int l, int r, const vi &a, int n)
{
    int len = 2 * n;
    while (l >= 0 && r < len && a[l] == a[r])
    {
        l--;
        r++;
    }
    l++;
    r--;

    if (l > r)
        return 0;
    vi v(n + 1, 0);
    for (int i = l; i <= r; i++)
    {
        if (a[i] <= n)
        {
            v[a[i]]++;
        }
    }
    int mex = 0;
    while (v[mex] > 0)
    {
        mex++;
    }
    return mex;
}

void solve()
{
    cin >> n;
    vi a(2 * n);

    int o1 = -1, o2 = -1;
    for (int i = 0; i < 2 * n; i++)
    {
        cin >> a[i];
        if (a[i] == 0)
        {
            if (o1 == -1)
                o1 = i;
            else
                o2 = i;
        }
    }
    int ans1 = f(o1, o1, a, n);
    int ans2 = f(o2, o2, a, n);
    int ans3 = f((o1 + o2) / 2, (o1 + o2 + 1) / 2, a, n);
    cout << max({ans1, ans2, ans3}) << endl;
}

E. It All Went Sideways

知识点:后缀最小值,思维

思路:用总的物体数量减去操作前不会移动的物体数量再加上操作后会移动的物体数量即为答案。总的物体数量累加即可。很容易发现如果某一高度的物体想不动,他后面每个位置至少是这个高度,对整个数组倒序求后缀最小值数组,累加即为原来不动的物体数量。如果我们对一个位置进行拿走物体操作,会发现这个位置之前与他后缀值相同的位置的后缀值都会跟着减少,减少的数量就是移动的数量,也就是我们只要求出具有相同后缀值的最长元素数量即可,因为要删去一个物体,记得减 \(1\).

点击查看代码
void solve()
{
    cin >> n;
    vi a(n + 1);
    vi b(n + 1);
    int sum1 = 0, sum2 = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        sum1 += a[i];
    }
    b[n] = a[n];
    for (int i = n - 1; i >= 1; i--)
    {
        b[i] = min(b[i + 1], a[i]);
        sum2 += b[i];
    }
    sum2 += b[n];
    int mx = 0;
    int now = 0;
    int num = -1;
    for (int i = 1; i <= n; i++)
    {
        if (num == b[i])
        {
            now++;
        }
        else
        {
            num = b[i];
            now = 1;
        }
        if (now > mx)
        {
            mx = now;
        }
    }
    cout << sum1 - sum2 + (mx - 1) << endl;
}

F. It Just Keeps Going Sideways

知识点:思维

思路:跟上个题一样,先计算不操作的答案,应该是重力改变后每一个物体所在的列数和减去初始时每一个物体所在的列数和,
后一项非常好计算,$\sum_{i=1}^{n}a_i*i $
前一项我们想一下最终位置应该是每一个高度的若干个物体堆积在最右面,这是一个等差数列,对每个高度进行等差数列相减即可(每个高度有多少个物体可以用差分做到)
这样我们就计算出了没有操作前的结果,
操作是对某一列拿走最高处的物体,想一想会对原答案产生什么影响,对于初始和,应该是会减去一个列编号,对于最终和,应该是会减去一个 \(n-h_{a_i}+1\),遍历每一列,计算这个最大值,加到结果中即可

Code
点击查看代码
int f(int x)
{
    return x * (x + 1) / 2;
}
void solve()
{
    cin >> n;
    vi a(n + 1);
    vi h(n + 4);
    int chu = 0;
    int mxh = 0;
    for (int i = 1; i <= n; i++)
    {
        cin >> a[i];
        h[1]++;
        h[a[i] + 1]--;
        mxh = max(a[i], mxh);
        chu += a[i] * i;
    }
    for (int i = 1; i <= n; i++)
    {
        h[i] += h[i - 1];
    }
    int hou = 0;
    for (int i = 1; i <= mxh; i++)
    {
        hou += f(n) - f(n - h[i]);
    }
    int res = 0;
    for (int i = 1; i <= n; i++)
    {
        res = max(res, i + f(n - h[a[i]]) - f(n - h[a[i]] + 1));
    }
    cout << hou - chu + res << endl;
}
posted @ 2026-05-02 00:00  Lambda_L  阅读(60)  评论(0)    收藏  举报