题目大意
给出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;
}
来源:oschina
链接:https://my.oschina.net/u/4409548/blog/3986843