D - Draw Your Cards(模拟)

用一个set维护当前所有堆对应的堆顶数。

每次lowerbound找,如果有则用链表插到表头。开一个数组记录cnt。

如果cnt=k,则遍历更新答案,然后从set里删掉堆顶。

每个元素最多遍历一次删除一次。

时间复杂度:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int n,k,ans[N],cnt[N],to[N];
set<int>s;
int main()
{
scanf("%d%d",&n,&k);
memset(ans,-1,sizeof(ans));
for(int i=1,x;i<=n;i++)
{
scanf("%d",&x);
auto it=s.lower_bound(x);
if(it==s.end())s.insert(x),cnt[x]=1;
else cnt[x]=cnt[*it]+1,to[x]=*it,s.erase(it),s.insert(x);
if(cnt[x]==k)
{
for(int j=x;j;j=to[j])ans[j]=i;
s.erase(s.find(x));
}
}
for(int i=1;i<=n;i++)printf("%d\n",ans[i]);
return 0;
}