Codeforces 1740I - Arranging Crystal Balls
(注:默认下标 1-indexed)
考虑一个数组被清零的充要条件:记 \(b_i=a_{i}-a_{(i+n-2)\bmod n+1}\),那么最终 \(a_i=0\) 当且仅当 \(b_i=0\) 且 \(a_1=0\)。
思考一次操作的影响:假设我们对 \([x,x+k-1]\) 这段环上的区间进行了 \(+v\),那么相当于是令 \(b_x\) 加 \(v\),\(b_{x+k}\) 减 \(v\)。同时如果这段区间经过了 \(1\),那么令 \(a_1\) 加 \(v\)。考虑在 \(i\) 与 \((i+k-1)\bmod n+1\) 之间连一条边,这样显然图会形成若干个环。每个环是独立的,并且由于我们要让 \(b_i\) 清零,所以钦定了环上一条边进行 \(+1\) 的次数之后,每条边进行 \(+1\) 的次数就确定了,这样总代价可以用 \(\sum \min(c_i,m-c_i)\) 来计算总代价,同时此次操作对 \(a_1\) 的影响也是可以计算的。
这样就有一个很显然的 DP 模型:\(dp_{i,j}\) 表示考虑了前 \(i\) 个环,目前 \(a_1=j\) 的最小代价,由于代价关于我们钦定的那条边的函数实际上是一个分段函数,且每一段都是一个一次函数,因此可以单调队列优化。总复杂度 \(\dfrac{n}{len}·m·len=nm\),其中 \(len\) 是环长。
代码咕了,明天再写。
upd:咕完了。
const int MAXN=1e6;
const ll INF=0x3f3f3f3f3f3f3f3fll;
int n,m,k,a[MAXN+5],b[MAXN+5],vis[MAXN+5];ll dp[MAXN+5];
int main(){
scanf("%d%d%d",&n,&m,&k);
for(int i=0;i<n;i++)scanf("%d",&a[i]);
for(int i=0;i<n;i++)b[i]=(a[i]-a[(i+n-1)%n]+m)%m;
// for(int i=0;i<n;i++)printf("%d%c",b[i]," \n"[i==n-1]);
memset(dp,63,sizeof(dp));dp[a[0]]=0;
for(int i=0;i<n;i++)if(!vis[i]){
vector<int>seq,val;
for(int j=i;!vis[j];j=(j+k)%n)seq.pb(j),vis[j]=1;
seq.pb(seq[0]);val.resize(seq.size(),0);
int sd=0;for(int j=1;j<seq.size();j++)sd=(sd+b[seq[j]])%m;
if(sd)return puts("-1"),0;
for(int j=2;j<seq.size();j++)val[j]=(val[j-1]-b[seq[j-1]]+m)%m;
static ll ndp[MAXN+5];
for(int j=0;j<m;j++)ndp[j]=INF;
int A=0,B=0;
for(int j=1;j<seq.size();j++)
if(seq[j-1]==0||(seq[j-1]>seq[j]&&seq[j]!=0))
A++,B=(B+val[j])%m;
static ll difa[MAXN+5],difb[MAXN+5];
auto add=[&](int l,int r,int a,int b){
// printf("[%d,%d] %dx+%d\n",l,r,a,b);
difa[l]+=a;difa[r+1]-=a;difb[l]+=b;difb[r+1]-=b;
};
for(int j=0;j<=m;j++)difa[j]=difb[j]=0;
for(int j=1;j<seq.size();j++){
int l=(m-val[j])%m,r=(m+(m>>1)-val[j])%m;
if(l<=r)add(l,r,1,-l);
else add(l,m-1,1,-l),add(0,r,1,m-l);
if(m!=2){
l=(m+(m>>1)+1-val[j])%m;r=(m-1-val[j])%m;
if(l<=r)add(l,r,-1,r+1);
else add(l,m-1,-1,r+1+m),add(0,r,-1,r+1);
}
}
for(int j=1;j<=m;j++)difa[j]+=difa[j-1],difb[j]+=difb[j-1];
for(int l=0,r;l<m;l=r){
r=l;while(r<m&&mp(difa[r],difb[r])==mp(difa[l],difb[l]))++r;
static bool vis[MAXN+5];for(int j=0;j<m;j++)vis[j]=0;
for(int j=0;j<m;j++)if(!vis[j]){
vector<int>vec;
for(int k=j;!vis[k];k=(k+A)%m)vis[k]=1,vec.pb(k);
int tmp=vec.size();
for(int k=0;k<tmp;k++)vec.pb(vec[k]);
static pair<ll,int> q[MAXN*2+5];int fr=1,tl=0;
for(int k=0;k<vec.size();k++){
while(fr<=tl&&q[fr].se<=k-(r-l))++fr;
ll val=dp[(vec[k]-1ll*A*l%m-B+m+m)%m]-1ll*difa[l]*k;
while(fr<=tl&&q[tl].fi>val)--tl;
q[++tl]=mp(val,k);
if(fr<=tl)chkmin(ndp[vec[k]],q[fr].fi+1ll*difa[l]*(l+k)+difb[l]);
}
}
}
for(int j=0;j<m;j++)dp[j]=ndp[j];
}
printf("%lld\n",(dp[0]==INF)?-1:dp[0]);
return 0;
}