2017CCPC 秦皇岛 A

有m个桌子组成的圆环,n个人坐在圆环里。(m>=n)

有q个A题信息,机器人负责给A题的人发气球,但是机器人只能顺时针走。

所有人们会有愤怒值,交题与获得气球的时间差为愤怒值,要求使得愤怒值之和最小。

考虑三点的圆环,发现其实所有的交题信息都可以转化为最多不同的三个状态。因为在一个环上从一点到另一点的距离只有n种可能,0..n-1。

推广到n个点,最多只有不同的n个状态。

我们把每个点的状态选一个代表点来研究问题。

比如三个点。(1,1)、(2,1)、(3,1)代表了所有的状态,任何其他的信息都与这三个之一等价,所以只用考虑这三个点。

先算出每个点从1出发的愤怒值。

当我们选中n个点其中一个点时,在这个点前面的点(愤怒值比它小的点)的愤怒值会增加m-angry[i]。从三个点可知愤怒值变化等同与距离变化。

同时在这个点后面的点(愤怒值比它大的点)愤怒值会减小angry[i]。

#include <bits/stdc++.h>
#define pb push_back
#define mp make_pair
#define x first
#define y second
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
#define up rt,rt<<1,rt<<1|1
#define mem(x) memset(x,0,sizeof(x))
#define mem1(x) memset(x,-1,sizeof(x))
#define LMissher
using namespace std;
typedef long long ll;
typedef double db;
const int M = 1e5+7;
const double pi = acos(-1);
const int inf = 2147483647;
const int mod = 1e9+7;

int _,n,a[M],m,p;
ll tot[M];

int main(){
    #ifdef LMissher
        freopen("1.in","r",stdin);
        freopen("1.out","w",stdout);
    #endif
    scanf("%d",&_);
    while(_--){
        ll cnt=0;//从1号桌出发的愤怒值
        scanf("%d%d%d",&n,&m,&p);//n people,m table ,p solved
        for(int i=1;i<=n;i++) scanf("%d",&a[i]);
        for(int i=1;i<=p;i++){
            ll team,time;
            scanf("%lld%lld",&team,&time);
            time%=m;if(time==0) time=m;//在交题的时间机器人走到哪个位置
            if(time<=a[team]) tot[i]=a[team]-time;//机器人在交题者的"前面"
            else tot[i]=1ll*m-time+a[team];//机器人在交题者的"后面"
            cnt+=tot[i];
        } 
        sort(tot+1,tot+p+1);//总共的状态其实最多只有n种,分别为0...n-1,不过不去重不影响答案
        ll ans=1e18;
        for(int i=1;i<=p;i++){
            ans=min(ans,cnt+1ll*(i-1)*(1ll*m-tot[i])-1ll*(p-i+1)*tot[i]);//枚举从不同位置出发
        }
        printf("%lld\n",ans);
    }
    return 0;
}
View Code

猜你喜欢

转载自www.cnblogs.com/LMissher/p/9631931.html
今日推荐