题解 P6035 【Ryoku 的逆序对】
feecle6418 · · 题解
第一问,每个为 -1 的位置
贪心地从前往后拼凑。假如 -1,就找当前没有选到的最小值。
现在的问题是怎么维护“第
这样说很抽象,看代码:
#include<bits/stdc++.h>
#define mod 1000000007
using namespace std;
int c[1000005],a[1000005],ans[1000005],used[1000005],n,now=1,s=1;
void Update(int x,int k) {
while(x<=n)c[x]+=k,x+=x&-x;
}
int Find(int x) {
int ret=0,now=0;
for(int i=19; i>=0; i--) {
if((ret+(1<<i))<=n&&now+c[ret+(1<<i)]<=x)ret+=(1<<i),now+=c[ret];// cout<<now<<' '<<ret<<endl;
}
return ret+1;
}
int main(){
scanf("%d",&n);
for(int i=1;i<=n;i++){
scanf("%d",&a[i]),Update(i,1);
if(a[i]>n-i)return puts("0"),0;
if(a[i]==-1)s=1ll*s*(n-i+1)%mod;
}
printf("%d\n",s);
for(int i=1;i<=n;i++){
if(~a[i]){
ans[i]=Find(a[i]);
Update(ans[i],-1);
used[ans[i]]=1;
}
else {
while(used[now])now++;
ans[i]=now;
Update(ans[i],-1);
used[ans[i]]=1;
}
printf("%d ",ans[i]);
}
return 0;
}