【GDOI2018】D1T2 密码锁(lock) - 差分 - 贪心

题目大意

  给出n个数,每次选择任意一个区间加或减1,求最少多少次能在$mod m$意义下全变成0。

Solution

  首先我们对于这n个数前后加个零,在$mod m$意义下差分一下。

  $f[i]=(a[i]-a[i-1]+m)mod m$

  于是区间加减1操作就转换成了在某一位加一,另一位减一。

  容易发现,每个数只会加到m或者减到1,而不会有多次循环。

  这样我们对差分序列排个序,在前半部分选择$l$减到1,后半部分选择$r$个加到n,($l+r=n$)

  这题就没了。

AC Code

#include <iostream>
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <cctype>
using namespace std;
#define MAXBUF 50000000
char buffer[MAXBUF];
int pos;
inline void load(){
    fread(buffer,1,MAXBUF,stdin);
    pos=0;
}
inline char gchar(){
    return buffer[pos++];
}
inline int rd(){
    int ret=0,f=1;char c=gchar();
    for(;!isdigit(c);)
        if(c=='-')f=-1,c=gchar();else c=gchar();
    for(;isdigit(c);)ret=ret*10+c-'0',c=gchar();
    return ret*f;

}
int n,m,nl,nr;
int f[500010],a[500010];
int main(){
    freopen("lock.in","r",stdin);
    load();
    n=rd();m=rd();
    for(int i=1;i<=n+1;i++)
        a[i]=rd(),
        f[i]=(a[i]-a[i-1]+m)%m;
    sort(f+1,f+n+2);
    for(int l=0,r=n+1;l<=r;)
        if(nl<=nr)
            nl+=f[l++];
        else nr+=m-f[r--];
    printf("%d\n",nl);
    return 0;
}

 

转载于:https://www.cnblogs.com/skylynf/p/8984782.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值