http://acm.zju.edu.cn/onlinejudge/showProblem.do?problemCode=3981
题意:
现在有n只队伍分布在m张桌子上(每个队伍在一张桌子上),现在有一个送气球的机器人,初始位置可以是这m个桌子的任意一个,机器人沿着顺时针方向沿着桌子走,如果机器人所在位置有队伍A了题目,机器人就会送上气球。现在如果某个队伍在Ta时刻A了题目,然后气球在Tb时刻被送到,那么此时的不开心值就有Tb-Ta。现在要使所有队伍的不开心值总和最小,问机器人一开始应该位于哪里。
思路:
现在假设机器人位于1号桌子处:
5个A题点需要等待的时间分别为 2 0 1 0 2。
如果初始机器人位于2号桌子处,那么需要等待的时间分别为 1 2 0 2 1。
可以发现,当机器人向右移动时,每个点等待的时间变为(t-1+m)%m。
但是对于每一个位置,你不可能去修改每个点的等待时间,这样时间复杂度太高了。
我们可以先计算出机器人位于1桌子时每个点的等待时间,然后排序,假设为d[i],对于d[i]来说,如果要让该点的等待时间为0,那么需要机器人向右移动d[i]个桌子,其余各点也就都需要减去d[i],由于已经按照时间排好了序,所以在i前面的那些点减去i之后肯定是小于0的,此时就需要为这些点加上m,总共需要加上i*m,所有点需要减去d[i],即q*d[i]。
1 #include<iostream> 2 #include<algorithm> 3 #include<cstring> 4 #include<cstdio> 5 #include<vector> 6 #include<stack> 7 #include<queue> 8 #include<cmath> 9 #include<map> 10 #include<set> 11 using namespace std; 12 typedef long long ll; 13 typedef pair<int,int> pll; 14 const int INF = 0x3f3f3f3f; 15 const int maxn = 1e5+5; 16 17 ll n, m, q; 18 ll p[maxn], d[maxn]; 19 20 int main() 21 { 22 //freopen("in.txt","r",stdin); 23 int T; 24 scanf("%d",&T); 25 while(T--) 26 { 27 scanf("%lld%lld%lld",&n,&m,&q); 28 for(int i=0;i<n;i++) scanf("%d",&p[i]); 29 30 ll sum = 0; 31 for(int i=0,j;i<q;i++) 32 { 33 ll t; 34 scanf("%d%lld",&j,&t); 35 d[i]=(p[j-1]-1-t%m+m)%m; 36 sum=sum+d[i]; 37 } 38 ll ans = (ll)1e18; 39 sort(d,d+q); 40 for(int i=0;i<q;i++) 41 { 42 if(i==0 || d[i]!=d[i-1]) 43 { 44 ans = min(ans, sum + i*m - q*d[i]); 45 } 46 } 47 cout<<ans<<endl; 48 } 49 return 0; 50 }