zoj 3981 Balloon Robot

https://vjudge.net/problem/ZOJ-3981

题意:

有m个座位,其中n个队伍坐在这些位置上,一个队伍一个座位。当一个队A了题之后,他们们会得到气球,假设他们在a时刻A题,但是在b时刻才得到气球,那么他们的不高兴值就会增加b - a。现在主办方安排了一个机器人发气球,机器人每时刻都会向右移动一个位置(当然是循环的),到了一个位置,如果这个位置上有队伍并且A了题没有得到气球,那么就会把气球发给这个队伍。现在给出每个队伍的位置和A题的情况,要求安排机器人的起始位置使得所有队伍的不开心值之和最小。

思路:

首先可以假设机器人在1位置,计算出每个题的气球需要等待的时间,然后接下来证明一个猜想,枚举的时间点必然是A题的时刻:

假设在当前枚举的时刻t没有A题,那么在枚举到t+1时刻,那么必然所有的A题的等待时间会减少1,直到有A题的时刻之后,时间才会增加。

首先把每个的等待时间排个序(求等待时间的时候,使用了二分法),之后顺序枚举

公式 ans = min(sum + i * m - d[i] * q),因为前面的A题时刻在起点后移之后必定会从m - 1开始递减的,所以有加上i * m,然后全部的等待时间都会减少d[i],所以每一个都减去。

总的时间复杂度为O(n)。

代码:

 1 #include <stdio.h>
 2 #include <string.h>
 3 #include <vector>
 4 #include <algorithm>
 5 using namespace std;
 6 
 7 int d[100005];
 8 int pos[100005];
 9 
10 bool meet(long long k,int tmp,int m,int b)
11 {
12     long long ans = k * m + tmp;
13 
14     if (ans >= b) return true;
15     else return false;
16 }
17 
18 int main()
19 {
20     int t;
21 
22     scanf("%d",&t);
23 
24     while (t--)
25     {
26         int n,m,p;
27 
28         scanf("%d%d%d",&n,&m,&p);
29 
30         long long sum = 0;
31 
32         for (int i = 1;i <= n;i++)
33             scanf("%d",&pos[i]);
34 
35         for (int i = 0;i < p;i++)
36         {
37             int a,b;
38 
39             scanf("%d%d",&a,&b);
40 
41             a = pos[a];
42 
43             long long l = 0,r = 1000000000;
44 
45             int tmp = a - 1;
46 
47             while (l < r - 1)
48             {
49                 long long mid = (l + r) >> 1;
50 
51                 if (meet(mid,tmp,m,b)) r = mid;
52                 else l = mid + 1;
53             }
54 
55             while (meet(r - 1,tmp,m,b)) r--;
56 
57             d[i] = r * m + tmp - b;
58 
59             sum += d[i];
60 
61             //printf("%d 233
",d[i]);
62         }
63 
64         sort(d,d+p);
65 
66         long long ans = 1000000000000000;
67 
68         for (int i = 0;i < p;i++)
69         {
70             long long tmp = sum + (long long)i * m - (long long) p * d[i];
71 
72             ans = min(tmp,ans);
73         }
74 
75         printf("%lld
",ans);
76     }
77 
78     return 0;
79 }
原文地址:https://www.cnblogs.com/kickit/p/7994997.html