题解:CF1870G MEXanization
首先容易发现,除了第一个数以外,后面的
于是我们考虑去 check 每个数是否能成为答案。
对于一个数
我们设
于是我们直接从大到小扫
这样直接模拟单次 check 能做到
考虑优化,先把上述的贪心换种形式:
我们设
于是我们对于每一个
其实容易发现,我们
考虑证明,由于
于是我们直接用线段树二分去找
接着考虑优化,由于直接找是真的没什么前途,所以我们考虑直接 dfs 线段树。
设
还是考虑我们刚刚的做法,在线段树上,我们依旧从后往前,但是时间复杂度是不变的。
考虑剪枝一下,也就是对于线段树上节点
发现这样写了后就可以通过了。
考虑分析一下时间复杂度:我们一层一层考虑,对于所有大小为
总时间复杂度为
#include<bits/stdc++.h>
#define ll long long
#define pc putchar
using namespace std;
inline int read(){
int x=0;bool f=0;char ch=getchar();
while(ch<'0'||ch>'9')f^=(ch=='-'),ch=getchar();
while('0'<=ch&&ch<='9')x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
return f?-x:x;
}
int pstk[40];
inline void write(int x){
if(!x)return putchar('0'),void();
if(x<0)putchar('-'),x=-x;
int len=0;for(;x;x/=10)pstk[++len]=x%10;
while(len)putchar(pstk[len--]+'0');
}
const int Maxn=2e5+5;
int n,a[Maxn];
struct Tree{int data,mn;}t[Maxn<<2];
int V[Maxn];
void build(int x,int l,int r){
if(l==r)return void(t[x]={0,0});
int mid=l+r>>1;
build(x<<1,l,mid);build(x<<1|1,mid+1,r);
}
void change(int x,int l,int r,int d,int p){
if(l==r){t[x].data+=p;t[x].mn+=p;return;}
int mid=l+r>>1;
if(mid>=d)change(x<<1,l,mid,d,p);
else change(x<<1|1,mid+1,r,d,p);
t[x].mn=min(t[x<<1].mn,t[x<<1|1].mn);
t[x].data=t[x<<1].data+t[x<<1|1].data;
}
int cnt[Maxn];
int ok;
void dfs(int x,int l,int r,int R,ll&d,ll&z){
if(ok)return;
if(t[x].mn-1>=d&&r<=R){
z+=1ll*t[x].data-1ll*(d+1)*(r-l+1);
return;
}
if(l==r){d+=1ll-1ll*(t[x].data-d);if(d>n)ok=1;return;}
int mid=l+r>>1;
if(mid<R)dfs(x<<1|1,mid+1,r,R,d,z);dfs(x<<1,l,mid,R,d,z);
}
inline bool check(int x){
ll d=0,z=0;
ok=0;if(x>1)dfs(1,1,n,x-1,d,z);
if(z+cnt[0]-d>=1){
cnt[0]-=V[x];cnt[x]=V[x];
change(1,1,n,x,V[x]);
return true;
}
return false;
}
inline void solve(){
n=read();
int ans=1;build(1,1,n);
for(int i=0;i<=n+1;i++)V[i]=cnt[i]=0;
for(int i=1;i<=n;i++){
a[i]=read();
V[a[i]]++;
if(a[i]>=ans||!a[i])cnt[0]++;
else change(1,1,n,a[i],1),cnt[a[i]]++;
if(i==1)write(max(1,a[i])),pc(' ');
else{
while(check(ans))ans++;
write(ans-1);pc(' ');
}
}
pc('\n');
}
int main(){
int T=read();
while(T--)solve();
return 0;
}
/*
20
18 12 18 6 4 14 11 5 8 8 6 11 11 6 18 2 1 6 13 11
1
6
4 3 0 0 0 0
*/