題目意思:n支隊伍,一張桌子有m個座位順時針編號1~m。p個預言。預言a隊伍在b時刻ac一道題目。機器人每一個時刻都順時針走一步,有須要氣球的就發。每支隊伍,ac後多少時刻沒收到氣球就有多少不開心的值,問機器人起始位置在哪裏可使得總的不高興值最小。輸出最小的不高興值。
思路:把每次預言轉一下,a,b。那就讓a隊伍位置往前推b的位置值加一。那麼不高興值就是機器人花費時間乘以值求和。而後換起始點能夠O(1)轉。
#include <stdio.h>
#include <iostream>
#include <algorithm>
#include <string.h>
#include <string>
#include <vector>
#include <map>
using namespace std;
typedef long long int LL;
const int maxn=1e6+10;
int n,m,p;
map<int,int>val;
int pos[maxn];
int main()
{
int T;
scanf("%d",&T);
while(T--)
{
scanf("%d%d%d",&n,&m,&p);
val.clear();
for(int i=1;i<=n;i++) scanf("%d",&pos[i]);
for(int i=1;i<=p;i++)
{
int x,y;
scanf("%d%d",&x,&y);
LL p=((pos[x]%m)*1ll-y+(1000000000ll/m+1)*m)%m;
val[(int)(p)]++;
}
LL sum=0,base=0,ans;
int st=val.begin()->first;;
for(map<int,int>::iterator i=val.begin();i!=val.end();i++)
{
sum+= i->second;
base+=(1ll*i->second*(i->first - st));
}
ans=base;
int prekey;
map<int,int>::iterator it=val.begin();
prekey=it->first;
int preval=it->second;
it++;
for(;it!=val.end();it++)
{
int dt=it->first-prekey;
base=base-((sum-preval)*dt)+(m-dt)*preval;
ans=min(base,ans);
prekey=it->first;
preval=it->second;
}
cout<<ans<<endl;
}
return 0;
}