The Contest(思维+前缀和)

题目链接:E. The Contest

题意:
三个人,每个人有一些数字,组合起来是一个排列,现在给你三个人手中数字的数量以及手中是哪几个数,每次操作可以把一个人手中的数字给另个人,问你最少多少次操作使得第一个人拥有这个排列的某个前缀,第三个人拥有这个排列的某个后缀,第二个人拥有中间剩下的部分(允许有人没有数字)。

思路:

  1. 看到三个人操作,我们先看两个人操作时的情况:
    假设到最后,第一个人拥有1 ~ i,第二个人拥有i+1 ~ n,那么最小操作数为第二个人1~i中拥有的数字加上第一个人i+1 ~ n中拥有的数字。我们可以采用前缀和,cnt1[k]表示第一个人前k个数中拥有的个数,cnt2[k]表示第二个人前k个数中拥有的个数,则表达式为:
    cnt2[i]+cnt1[n]−cnt1[i]
  2. 受到启发我们看三个人操作时的情况:
    假设到最后,第一个人拥有1 ~ i,第二个人拥有i+1 ~ j,第三个人拥有j+1 ~ n,那么最小操作数为第二个人和第三个人1 ~ i中拥有的个数加上第一个人和第三个人i+1 ~ j中拥有的个数加上第一个人和第二个人j+1 ~ n中拥有的个数。我们可以采用前缀和,cnt1[k]表示第一个人前k个数中拥有的个数,cnt2[k]表示第二个人前k个数中拥有的个数,cnt3[k]表示第三个人前k个数中拥有的个数字表达式为:
    cnt2[i]+cnt3[i]+cnt1[j]−cnt1[i]+cnt3[j]−cnt3[i]+cnt1[n]−cnt1[j]+cnt2[n]−cnt2[j]
  3. 化简得到:
    cnt2[i]−cnt1[i]+cnt3[j]−cnt2[j]+cnt1[n]+cnt2[n]
  4. 我们从0~n枚举i,接下来我们考虑j的取值,我们可以看到对于固定的i,只需要找到一个j使得该式子最小即可,那么我们可以设置一个后缀minn[]数组,minn[i]表示当i≤j≤n时,cnt3[j]−cnt2[j]最小的值,那么答案即为:
    cnt2[i]−cnt1[i]+minn[i]+cnt1[n]+cnt2[n]

参考博客:CODEFORCES 1257E - THE CONTEST

#include<bits/stdc++.h>
#define inf 0x3f3f3f3f
using namespace std;

typedef long long ll;

const int N = 200010;

int n, m, k;
int num1[N];
int num2[N];
int num3[N];
int mini[N];
int a[N], b[N], c[N];

int main()
{
    scanf("%d %d %d", &n, &m, &k);
    int tot = n + m + k;
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &a[i]);
        num1[a[i]]++;
    }
    for(int i = 1; i <= m; i++)
    {
        scanf("%d", &b[i]);
        num2[b[i]]++;
    }
    for(int i = 1; i <= k; i++)
    {
        scanf("%d", &c[i]);
        num3[c[i]]++;
    }
    for(int i = 1; i <= tot; i++)
    {
        num1[i] += num1[i - 1];
        num2[i] += num2[i - 1];
        num3[i] += num3[i - 1];
    }
    mini[tot + 1] = inf;
    for(int i = tot; i >= 0; i--)
    {
        int now = num3[i] - num2[i];
        mini[i] = min(mini[i + 1], now);
    }
    int ans = inf;
    for(int i = 0; i <= tot; i++)
    {
        int now = num2[i] - num1[i] + num1[tot] + num2[tot] + mini[i];
        ans = min(ans, now);
    }
    printf("%d\n", ans);
    return 0;
}

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章