传送门 点我
推销 点我
题意
翻译非常好懂,非常敬业。
思路
看到很多题解是二分的,感觉,是不是有点小题大做了……
提供一个利用数学中的周期问题的方法。
假设每一个数都不会被消去,你只需要不停地减,那么相信大家一定都会做,即使那个 这么大。
但一个数是会被消去的。
我们来考虑一下:如果一个数要被消去,那么它的数值要变成 ,所以我们可以算出,假设它的数值为 ,一共有 个数而且其他数都不比它小,那么它理应会在第 次被消去。
但是这样有两个限制:
- 这个数不一定在第一位。
- 剩下的数不一定都不比它小。
这个时候,我们是否可以把最后的那一下补完一个周期,那么就可以对其进行排序,然后从数值小的开始一个个消去,最后的几个再暴力模拟一下就行了!
Code
#include<bits/stdc++.h>
using namespace std;
long long n,m,i,sum,x,flag;
struct Node{
long long x,i;
}a[100010];
bool cmp(Node x,Node y){return x.x<y.x;}
bool cmp1(Node x,Node y){return x.i<y.i;}
int main(){
scanf("%lld%lld",&n,&m);
for (i=1;i<=n;i++) scanf("%lld",&a[i].x),a[i].i=i;
sort(a+1,a+n+1,cmp);
for (i=1;i<=n;i++)
if (sum+(a[i].x-x)*(n-i+1)<=m) sum=sum+(a[i].x-x)*(n-i+1),x=a[i].x;
else break;
if (i>n&&sum<m){printf("-1\n");return 0;}
else if (i>n&&sum==m) return 0;
x=x+(m-sum)/(n-i+1);m=(m-sum)%(n-i+1);
i=1;sort(a+1,a+n+1,cmp1);
while (m>0){
if (a[i].x>x) a[i].x--,m--;
i=i%n+1;
}
int h=i;
for (i=1;i<=n;i++,h=h%n+1) if (a[h].x>x) printf("%lld ",a[h].i);
return 0;
}