【2017 CCPC 秦皇岛】A.Balloon Robot 思维

题目链接

题意

现在正在举行一场程序设计竞赛,有 n 个选手,一张有 m 个座位的圆形桌子。现在给出 n 个队伍坐的位置,以及 p 个正确的提交,每个提交给出某队伍在某小时ac了一道题目。

现在有个机器人专门给ac的队伍发气球,假如他初始位置在 1.
它会依次执行以下步骤:

  1. 假如当前位置为 \(pos\) ,\(pos\)变为\(pos\%m+1\),即向后走一步
  2. 如果当前位置此时有未发的气球,那么给这个队伍一个气球。

对于每个队伍,假如它ac某题的时间为 \(t_1\),收到气球的时间为 \(t_2\),他会产生一个不开心值 \(t_2-t_1\)

现在让你选定一个机器人的初始位置,使得所有队伍的总不开心值最小。

思路

首先我们求出来机器人在位置 \(1\) 时,每个队伍的不开心度 \(val[i]\)

我们来看当初始位置从 \(1\) 挪到 \(2\) 的时候每个队伍不开心度的变化。

开心度为 \(0\) ,那么会变成 \(m-1\),如果开心值不为 \(0\) ,那么会减少 \(1\)

但是 \(m\) 这么大,肯定不能枚举所有的位置。

我就想应该是枚举 \(p\) 个ac,对于第 \(i\) 个ac,我们假设起点 \(x\) 满足第 \(i\) 个ac的不开心值为 \(0\)

得到起点 \(x\) 之后,假设以 \(1\) 为初始位置的位于区间 \([0,x-1]\) 的不开心值的个数有 \(num\) 个,那么初始位置从 \(1\) 变到 \(x\)\(num\) 个不开心值增加了 \(m-1\)\((x-1)*p-num\) 个不开心值减少了 \(1\),总不开心值增加了 \(num*m+(x-1)*p\)

得到的新的不开心值和 和以 \(1\) 为开始的不开心值和取小值即可。

代码

/*
 * @Autor: valk
 * @Date: 2020-08-21 11:06:28
 * @LastEditTime: 2020-10-21 20:22:14
 * @Description: 如果邪恶  是华丽残酷的乐章 它的终场 我会亲手写上 晨曦的光 风干最后一行忧伤 黑色的墨 染上安详
 */
#include <algorithm>
#include <iostream>
#include <map>
#include <math.h>
#include <queue>
#include <set>
#include <stack>
#include <stdio.h>
#include <string.h>
#include <string>
#include <vector>
#define emplace_back push_back
#define pb push_back
using namespace std;
typedef long long ll;
typedef unsigned long long ull;
const ll mod = 1e9 + 7;
const ll seed = 12289;
const double eps = 1e-6;
const ll inf = 0x3f3f3f3f;
const ll N = 2e5 + 10;

ll pos[N], val[N];

struct note {
    ll pos, t, val;
} arr[N];

int main()
{
    int T;
    scanf("%d", &T);
    while (T--) {
        ll n, m, p;
        scanf("%lld%lld%lld", &n, &m, &p);
        for (ll i = 1; i <= n; i++) {
            scanf("%lld", &pos[i]);
        }
        ll sum = 0;
        for (ll i = 1; i <= p; i++) {
            scanf("%lld%lld", &arr[i].pos, &arr[i].t);
            arr[i].pos = pos[arr[i].pos];
            val[i] = ((arr[i].pos - 1 - arr[i].t) % m + m) % m;
            arr[i].val = val[i];
            sum += val[i];
        }
        sort(val + 1, val + 1 + p);
        ll ans = sum;
        for (ll i = 1; i <= p; i++) {
            if (!arr[i].val)
                continue;
            ll now = ((arr[i].pos - arr[i].t + m) % m - 1 + m) % m;//得到使得该ac,不开心值为0的初始位置的移动次数
            ll num = upper_bound(val + 1, val + 1 + p, now - 1) - val - 1;
            ll temp = sum - now * p + num * m;
            ans = min(ans, temp);
        }
        printf("%lld\n", ans);
    }
    return 0;
}
posted @ 2020-10-21 20:40  Valk3  阅读(100)  评论(0编辑  收藏  举报