题意:
就是给你一个n长度的数组,然后问你当整个数组的MEX为i的时候,最小操作次数是多少,每次操作可以让数组中的一个数+1,i从0到n。
思考:
咋说呢,这个题和之前做过的一题挺像的,从前往后开始处理。这种题目如果你想直接求每一次的操作,去找什么非法情况,多少大于它的多少小于它的,这实在是太复杂了。想一想就是从0到n一次顺序的来,操作次数就是sum+当前这个数的个数。然后把这个数留一个,然后剩下的放到大根堆里面。如果当前这个数的个数不足1,那么就从队列里面拿出来一个,记录一下。如果队列是空的,直接break,后面的都不合法。
代码:
int T,n,m;
int va[N];
int anw[N];
signed main()
{
IOS;
cin>>T;
while(T--)
{
cin>>n;
for(int i=1;i<=n;i++) anw[i] = -1;
for(int i=1;i<=n;i++) cin>>va[i];
sort(va+1,va+1+n);
int sum = 0;
map<int,int > mp;
priority_queue<int > q;
for(int i=1;i<=n;i++) mp[va[i]]++;
for(int i=0;i<=n;i++)
{
anw[i] = sum+mp[i];
if(mp[i])
{
while(mp[i]-->1)
q.push(i);
}
else
{
if(q.size()==0) break;
sum += i-q.top();
q.pop();
}
}
for(int i=0;i<=n;i++) cout<<anw[i]<<" ";
cout<<"\n";
}
return 0;
}
总结:
不要其弄太复杂的,仔细思考思考,用手模拟模拟,什么时候可以该怎么办,什么时候退出,这都是固定的。