/*
zoj3981 思维题
Author: lcy
Time: 2017-11-3
有多支ACM队伍在环形上,给出他们AC的时间。
现在有一个机器人,从某一起点开始顺时针绕圈,
如果路过某支队伍时,该队恰好AC或在之前AC但没有气球,
那么机器人给该队发一个气球。从AC到拿到气球的时间为等待时间,
现在需要让所有队伍的等待时间最小。

思路参照http://blog.csdn.net/yasola/article/details/78391754

每一次AC记录含有两个变量,即位置与时间。
事实上,我们可以把时间这一维去掉,让所有人都在1分钟交题。
这样每个队要么在机器人跑第一圈时就拿到气球,要么第二圈就能拿到。
这样处理后,交题队伍要重新安排。

那么如何让时间最短呢?
想象机器人的起始位置顺时针运动1步,如果此时的位置上没有队伍
(现在所有人都在1分钟交题),此时所有队伍都会快1分钟拿到气球,
所以时间总和较移动前减小p。
假如起始位置这样一直移动下去,当起始位置上有队伍时,根据题意,
此时机器人会先移动下一格,然后该位置队伍交题,这意味着该队伍
只能在第二圈拿到气球,这个时候时间会增加。所以,枚举机器人的起点
时,我们只考虑某个队伍前一个位置,这样该队可以一开始就拿到气球,
而递减关系可以得到维护。时间复杂度O(p)
*/
#include <bits/stdc++.h>
using namespace std;
#define ll long long
#define fr(i,a,b) for(int i=a;i<=b;i++)
#define frr(i,a,b) for(int i=a;i>=b;i--)
#define ms(a,b) memset(a,b,sizeof(a))
#define scfd(a) scanf("%d",a)
#define scflf(a) scanf("%lf",a)
#define scfs(a) scanf("%s",a)
#define ptfd(a) printf("%d\n",a)
#define ptfs(a) printf("%s\n",a)
#define showd(a,b) printf(a"=%d\n",b)
#define showlf(a,b) printf(a"=%lf\n",b)
#define shows(a,b) printf(a"=%s\n",b)
#define mmcp(a,b) memcpy(a,b,sizeof(b))
#define pb(a) push_back(a)
const int MAXN=100005;
int cases,n,m,p,tot,ed;
map<int,int>mp;
ll s[MAXN],cnt[MAXN],pm[MAXN],aa[MAXN];
inline void init(){
	mp.clear();
	ms(cnt,0);
	ed=tot=0;
}
int main(){
	ios::sync_with_stdio(false);cin.tie(0);
	cin>>cases;
	while(cases--){
		init();
		cin>>n>>m>>p;	
		fr(i,1,n){cin>>aa[i];aa[i]--;}	
		fr(i,1,p){
			int a,b;	
			cin>>a>>b;
			s[ed++]=(aa[a]-(b-1)%m+m)%m;
		}
		sort(s,s+ed);
		fr(i,0,ed-1)if(!mp.count(s[i])){mp[s[i]]=tot,pm[tot]=s[i];tot++;}
		fr(i,0,ed-1)cnt[mp[s[i]]]++;
		ll ans=0;
		fr(i,1,tot-1)ans+=(pm[i]-pm[0])*cnt[i];	
		ll t=ans;
		fr(i,1,tot-1){
			t+=cnt[i-1]*(ll)(m-pm[i]+pm[i-1])-(pm[i]-pm[i-1])*(ll)(p-cnt[i-1]);
			ans=min(ans,t);
		}
		cout<<ans<<endl;
	}
	return 0;
}

 posted on 2017-11-03 15:46  cylcy  阅读(127)  评论(0编辑  收藏  举报