Codeforces Round #679 (Div. 2)/1435C Perform Easily

题目链接:https://codeforces.com/contest/1435/problem/C

题目大意:给定6个ai[1,…,6],n个bj[1,…,n],求数列x (x = bj - ai 每个b只能用一次)中最大值与最小值差值的最小值

题目思路:因为每个b只能用一次,所以我们必须找到最合适的数列x,使得x的最大值与最小值差值的最小,因此我们需要求出每个b对应的所有x(因为有6个ai,最坏有6n个x),遍历x使最小值不断变大,最大值不断变小,从而求出结果。这里我用pair存储,first存x,second存i,排序后,用vis存储i是否用过,若用过,更新i,若没用过,则记录,然后判断使用总数是否等于n,若等于,则求结果,上样例!

图片替换文本

我们发现ai中有重复的数字,所以我们可以先对a进行排序去重,然后得到a实际上就3个值:1,2,3,然后去求pair,排序后得(1,2) (2,2) (3,2) (8,3) (8,5) (9,3) (9,4) (9,5) (9,7) (10,1) (10,3) (10,4) (10,5) (10,6) (10,7) (11,1) (11,4) (11,6) (11,7) (12,1) (12,6),遍历(1,2)时将最小值变为1,即vis[7] = {INF,1,INF,INF,INF,INF,INF},遍历(2,2)时,发现现有最小值可以变大,即vis[7] = {INF,2,INF,INF,INF,INF,INF},以此类推,当第一次vis全部都不是INF时,即遍历到(10,7)时,vis[7] = {10,3,10,10,10,10,10},此时ans = 10 - 3 = 7,遍历到(11,1)时,vis[7] = {11,3,10,10,10,10,10},此时ans = 11 - 3 = 8,遍历到(12,1)时,vis[7] = {12,3,10,11,10,11,11},此时ans = 12 - 3 = 9 以此类推,求出ans的最小值,但是我们发现取最大值好说,就是当前遍历到的x(first),而最小值需要对vis进行遍历,这样循环套循环,时间复杂度是o(n2),所以用map存储,map可以自动排序,我们取第一个就行(记得更新的时候删除以前的最小值)
AC代码:

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <vector>
#include <map>
#include <string>
#include <cstring>
#include <set>
#include <stack>
#include <deque>
#include <queue>
using namespace std;
typedef pair<int, int> PII;
typedef long long ll;
typedef unsigned long long ull;
const int INF = 0x3f3f3f3f;
const int N = 100010, M = 5 * N;
const int base = 1e9;
const int P = 131;
const int mod = 1e9 + 7;
int n, m;
PII b[N * 6];
int vis[N];
int main()
{
    vector<int> a;
    for (int i = 1; i <= 6; ++i)
    {
        int x;
        scanf("%d", &x);
        a.push_back(x);
    }
    sort(a.begin(), a.end());
    a.erase(unique(a.begin(), a.end()), a.end());//对a排序去重
    scanf("%d", &n);
    int idx = 0;
    for (int i = 1; i <= n; ++i)
    {
        int x;
        scanf("%d", &x);
        for (int j = 0; j < a.size(); ++j)
            b[++idx] = {x - a[j], i};//求b,first存x,second存i
    }
    sort(b + 1, b + idx + 1);
    int res = 0;
    map<int, int> mp;//用map存储最小值
    int ans = INF;
    for (int i = 1; i <= idx; ++i)
    {
        int x2 = b[i].first, p = b[i].second;
        printf("(%d,%d) ", x2, p);
        if (vis[p] == 0)
            ++res;//用过的次数+1
        else
        {
            --mp[vis[p]];
            if (mp[vis[p]] == 0)
                mp.erase(vis[p]);//删除最小值
        }
        vis[p] = x2;
        ++mp[vis[p]];//更新最小值
        if (res == n)//求ans
        {
            int x1 = mp.begin()->first;
            ans = min(ans, x2 - x1);
        }
    }
    printf("%d\n", ans);
    return 0;
}
posted @ 2020-10-31 11:19  xiaopangpang7  阅读(143)  评论(0编辑  收藏  举报