Balloon Robot ZOJ - 3981

大意: n个参赛队, m个座位, 一共交了p次题, 一个机器人每秒钟会从位置$i$走到$i+1$, 若在$m$直接走到$1$, 当走到一个队伍就给该队应得的气球. 对于每道题, 假设交题时间$t_a$, 给气球时间$t_b$, 则该题的不满意度为$t_b-t_a$. 求机器人初始位置, 使得总不满意度最小.

 

 

假设初始位置为$x$, 显然对于位置为$pos$的队伍每道题的贡献就为 $pos-x-t\space (mod\space m)$.

要求的就是$x$在范围[1,m]的贡献和的最小值, 考虑$x$增大时贡献的变化, 显然对于当前贡献为$0$的会变为$m-1$, 其余的贡献均减一, 所有预处理出$x=1$时的贡献, 然后递推即可$O(m)$, 但是题目的$m$非常大, 注意到最优时一定有一道题贡献恰好为0, 按贡献排序后枚举为0的题即可.

这题数据量太大了, scanf直接被卡, 要用cin或者快读

#include <iostream>
#include <algorithm>
#include <cstdio>
#include <math.h>
#include <set>
#include <map>
#include <queue>
#include <string>
#include <string.h>
#include <bitset>
#define REP(i,a,n) for(int i=a;i<=n;++i)
#define PER(i,a,n) for(int i=n;i>=a;--i)
#define hr putchar(10)
#define pb push_back
#define lc (o<<1)
#define rc (lc|1)
#define mid ((l+r)>>1)
#define ls lc,l,mid
#define rs rc,mid+1,r
#define x first
#define y second
#define io std::ios::sync_with_stdio(false)
#define endl '\n'
#define DB(a) ({REP(__i,1,n) cout<<a[__i]<<' ';hr;})
using namespace std;
typedef long long ll;
typedef pair<int,int> pii;
const int P = 1e9+7, INF = 0x3f3f3f3f;
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
ll qpow(ll a,ll n) {ll r=1%P;for (a%=P;n;a=a*a%P,n>>=1)if(n&1)r=r*a%P;return r;}
ll inv(ll x){return x<=1?1:inv(P%x)*(P-P/x)%P;}
inline int rd() {int x=0;char p=getchar();while(p<'0'||p>'9')p=getchar();while(p>='0'&&p<='9')x=x*10+p-'0',p=getchar();return x;}
//head


const int N = 1e6+10;
int n, m, p, pos[N], c[N];

void work() {
	n=rd(),m=rd(),p=rd();
	REP(i,1,n) pos[i]=rd();
	ll sum = 0;
	REP(i,1,p) {
		int a=rd(), b=rd();
		c[i] = ((ll)pos[a]-1-b)%m;
		if (c[i]<0) c[i] += m;
		sum += c[i];
	}
	sort(c+1,c+1+p);
	ll ans = sum;
	REP(i,1,p) {
		ans = min(ans, sum+(ll)m*(i-1)-(ll)c[i]*p);
	}
	printf("%lld\n", ans);
}

int main() {
	int t;
	scanf("%d", &t);
	while (t--) work();
}

 

posted @ 2019-05-02 18:32  uid001  阅读(154)  评论(0编辑  收藏  举报