1 条题解
-
0
题目大意
给定 ,每次操作可以给 个不同的 加一(在 意义下),求至少几次操作能让 变成 的排列。
数据范围:。
思路分析
考虑在不 意义下确定最终的 ,要满足如下条件:
- 。
- 互不相同。
- 记 ,那么 。
- 。
首先只有第一个条件和 的相对顺序有关,为了满足这个条件,显然同时将 升序排列最优。
然后考虑第四个条件,对于一组合法解 ,如果 ,那么调整 。
显然不影响条件一、二、三的合法性,且此时 会变小,且 ,因此 也会变小。
因此这样调整一定更优,最终一定有 ,即 是连续的一段,存在一个 使得 。
那么逐个满足条件即可,先找到 ,然后调整到最近的 使得 。
找到此时的 ,如果 ,那么接下来就会进行若干次调整,每次会令 加上 。
此时 加上 ,且 加上 ,由于 因此这个调整总能结束。
时间复杂度 。
代码呈现
#include<bits/stdc++.h> #define ll long long using namespace std; const int MAXN=2.5e5+5; int n,m,a[MAXN],g; ll sum,k=0; signed main() { scanf("%d%d",&n,&m),g=__gcd(n,m); for(int i=0;i<n;++i) scanf("%d",&a[i]),sum+=a[i]; if((1ll*n*(n-1)/2-sum)%g) return puts("-1"),0; sort(a,a+n); for(int i=0;i<n;++i) k=max(k,(ll)a[i]-i); sum=(2*k+n-1)*n/2-sum; while(sum%m) ++k,sum+=n; ll mx=0,d=m/__gcd(n,m),c=n*d/m; for(int i=0;i<n;++i) mx=max(mx,k+i-a[i]); if(mx>sum/m) { ll cur=(mx-sum/m-1)/(c-d)+1; printf("%lld\n",sum/m+cur*c); } else printf("%lld\n",sum/m); return 0; }
- 1
信息
- ID
- 11518
- 时间
- 2000ms
- 内存
- 1024MiB
- 难度
- 10
- 标签
- 递交数
- 2
- 已通过
- 1
- 上传者