D. Misha and Permutations Summation
time limit per test2 seconds
memory limit per test256 megabytes
inputstandard input
outputstandard output
Let’s define the sum of two permutations p and q of numbers 0, 1, …, (n - 1) as permutation , where Perm(x) is the x-th lexicographically permutation of numbers 0, 1, …, (n - 1) (counting from zero), and Ord§ is the number of permutation p in the lexicographical order.
For example, Perm(0) = (0, 1, …, n - 2, n - 1), Perm(n! - 1) = (n - 1, n - 2, …, 1, 0)
Misha has two permutations, p and q. Your task is to find their sum.
Permutation a = (a 0, a 1, …, a n - 1) is called to be lexicographically smaller than permutation b = (b 0, b 1, …, b n - 1), if for some k following conditions hold: a 0 = b 0, a 1 = b 1, …, a k - 1 = b k - 1, a k < b k.
Input
The first line contains an integer n (1 ≤ n ≤ 200 000).
The second line contains n distinct integers from 0 to n - 1, separated by a space, forming permutation p.
The third line contains n distinct integers from 0 to n - 1, separated by spaces, forming permutation q.
Output
Print n distinct integers from 0 to n - 1, forming the sum of the given permutations. Separate the numbers by spaces.
Examples
inputCopy
2
0 1
0 1
outputCopy
0 1
inputCopy
2
0 1
1 0
outputCopy
1 0
inputCopy
3
1 2 0
2 1 0
outputCopy
1 0 2
Note
Permutations of numbers from 0 to 1 in the lexicographical order: (0, 1), (1, 0).
In the first sample Ord§ = 0 and Ord(q) = 0, so the answer is .
In the second sample Ord§ = 0 and Ord(q) = 1, so the answer is .
Permutations of numbers from 0 to 2 in the lexicographical order: (0, 1, 2), (0, 2, 1), (1, 0, 2), (1, 2, 0), (2, 0, 1), (2, 1, 0).
In the third sample Ord§ = 3 and Ord(q) = 5, so the answer is .
变进制数康托展开,大佬博客点这里
#include<bits/stdc++.h>
using namespace std;
const int N=2e5+500;
int a[N],b[N],c[N],ans[N];
int bit[N];
int n;
struct tree {
int data;
int l,r;
} t[N*4];
void add(int x) {
while(x<=n) {
bit[x]++;
x+=x&-x;
}
return;
}
int ask(int x) {
int ans=0;
while(x) {
ans+=bit[x];
x-=x&-x;
}
return ans;
}
void pushup(int p) {
t[p].data=t[p*2].data+t[p*2+1].data;
return;
}
void build(int p,int l,int r) {
t[p].data=0;
t[p].l=l;
t[p].r=r;
if(l==r)return;
int mid=(l+r)/2;
build(p*2,l,mid);
build(p*2+1,mid+1,r);
}
void change(int p,int x) {
if(t[p].l==t[p].r) {
t[p].data=1;
return;
}
int mid=(t[p].l+t[p].r)/2;
if(x<=mid)change(p*2,x);
else change(p*2+1,x);
pushup(p);
}
int Ask(int p,int x) {
if(t[p].l==t[p].r) {
return t[p].l;
}
int mid=(t[p].l+t[p].r)/2;
if(mid-t[p].l+1-t[p*2].data>x)Ask(p*2,x);
else Ask(p*2+1,x-(mid-t[p].l+1-t[p*2].data));
}
int main() {
scanf("%d",&n);
int x;
for(int i=1; i<=n; ++i) {
scanf("%d",&x);
x++;
a[i]=x-1-ask(x);
add(x);
}
memset(bit,0,sizeof(bit));
for(int i=1; i<=n; ++i) {
scanf("%d",&x);
x++;
b[i]=x-1-ask(x);
add(x);
}
int yu=0;
for(int i=n; i>=1; --i) {
c[i]=(a[i]+b[i]+yu)%(n+1-i);
yu=(a[i]+b[i]+yu)/(n+1-i);
}
build(1,1,n);
for(int i=1; i<=n; ++i) {
ans[i]=Ask(1,c[i]);
change(1,ans[i]);
}
for(int i=1; i<=n; ++i) {
printf("%d ",ans[i]-1);
}
return 0;
}