ccpc秦皇岛部分题解

A.

题意:就是有一个大桌子,环绕有顺势站1~m共m个座位,n个选手坐在部分位置上。然后如果有一个人a了一道题,却没有立刻发气球给他,他产生怒气值是发气球给他的时间减去a题时间。现在有一个机器人顺时针环绕桌子发球,每个单位时间走过一个位置。问机器人在哪个位置开始发气球总怒气值最小,输出最小怒气值。


其实是个傻逼思维题。假如他从位置m开始发气球,对于每个位置i,他到达的时间为k*m+i,所以对于每个它在时刻t a的题,他需要等待t-(k*m+i)中最小的正整数时间。随便算算就能知道每一题从m位置开始具体产生的怒气值,从而算出怒气总值作为初始值(当然从其他位置也行)。然后他往逆时针移动一个位置开始,相当于所有a题时间在%m的意义下+1。因此我们从小到大排个序,从最后一个数字往第一个数字遍历一遍,每次的操作都是把该为数字加到0的数加到所有题上,算算总的怒气值,在这里面一定产生一个最小的怒气值。

 1 #include<bits/stdc++.h>
 2 #define clr(x) memset(x,0,sizeof(x))
 3 #define clr_1(x) memset(x,-1,sizeof(x))
 4 #define mod 1000000007
 5 #define LL long long
 6 using namespace std;
 7 const int N=200010;
 8 int n,m,q,k,T,u,v;
 9 int pos[N],info[N];
10 LL pp,qq,tt,ans,all;
11 int main()
12 {
13     scanf("%d",&T);
14     while(T--)
15     {
16         scanf("%d%d%d",&n,&m,&q);
17         for(int i=1;i<=n;i++)
18         {
19             scanf("%d",&pos[i]);
20             if(pos[i]==m)
21                 pos[i]=0;
22         }
23         all=0;
24         for(int i=1;i<=q;i++)
25         {
26             scanf("%d%d",&u,&v);
27             v=v%m;
28             info[i]=(pos[u]-v+m)%m;
29             all+=info[i];
30         }
31         n=q;
32         sort(info+1,info+n+1);
33         LL qq=0;
34         ans=all;
35         for(int i=n;i>=1;i--)
36         {
37             pp=m-(info[i]+qq);
38             all-=(LL)info[i]+qq;
39             all+=pp*(n-1);
40             qq+=pp;
41             if(all<ans)
42                 ans=all;
43         }
44         printf("%lld\n",ans);
45     }
46     return 0;
47 }
View Code

 

posted @ 2017-11-04 01:25  hk_lin  阅读(1726)  评论(2编辑  收藏  举报