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(p) 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 = (a0, a1, ..., an - 1) is called to be lexicographically smaller than permutation b = (b0, b1, ..., bn - 1), if for some kfollowing conditions hold: a0 = b0, a1 = b1, ..., ak - 1 = bk - 1, ak < bk.
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.
Print n distinct integers from 0 to n - 1, forming the sum of the given permutations. Separate the numbers by spaces.
2 0 1 0 1
0 1
2 0 1 1 0
1 0
3 1 2 0 2 1 0
1 0 2
题意:给你两个序列的排列情况,问你这两个排列的序号的和的排列是什么。
思路:首先用树状数组求当前排列的序号,其中数组num[i]表示其中i!的系数,然后把两个都加起来再进位。
AC代码如下:
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#include<cmath>
using namespace std;
typedef long long ll;
int tree[200010],num[200010];
int n;
int lowbit(int x)
{
return x&(-x);
}
void update(int x,int date)
{
for(;x<=n;x+=lowbit(x))
tree[x]+=date;
}
int query(int x)
{
int sum=0;
for(;x>0;x-=lowbit(x))
sum+=tree[x];
return sum;
}
int find(int k)
{
int l=1,r=n,mi,p;
while(l<r)
{
mi=(l+r)/2;
p=query(mi);
if(p<k)
l=mi+1;
else
r=mi;
}
update(l,-1);
return l;
}
int main()
{
int T,t,i,j,u,p;
int k,m;
scanf("%d",&n);
for(i=1;i<=n;i++)
update(i,1);
for(i=n-1;i>=0;i--)
{
scanf("%d",&u);
u++;
update(u,-1);
m=query(u);
num[i]+=m;
}
for(i=1;i<=n;i++)
update(i,1);
for(i=n-1;i>=0;i--)
{
scanf("%d",&u);
u++;
update(u,-1);
m=query(u);
num[i]+=m;
}
for(i=1;i<n;i++)
{
k=num[i]/(i+1);
num[i]%=(i+1);
num[i+1]+=k;
}
for(i=1;i<=n;i++)
update(i,1);
for(i=n-1;i>=1;i--)
{
p=find(num[i]+1)-1;
printf("%d ",p);
}
printf("%d\n",find(1)-1);
}