Codeforces 501D Misha and Permutations Summation (康托展开+平衡树优化)

D. Misha and Permutations Summation
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard 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(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.

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.

Sample test(s)
input
2
0 1
0 1
output
0 1
input
2
0 1
1 0
output
1 0
input
3
1 2 0
2 1 0
output
1 0 2
Note

Permutations of numbers from 0 to 1 in the lexicographical order: (0, 1), (1, 0).

In the first sample Ord(p) = 0 and Ord(q) = 0, so the answer is .

In the second sample Ord(p) = 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(p) = 3 and Ord(q) = 5, so the answer is .



题意:

给定n,记Perm(x)是所有0,1,2,...,n-1的排列中第x大的排列,对于一个0,1,2,...,n-1的排列p,记p是所有0,1,2,...,n-1的排列中字典序从小到大的第Ord(p)个排列,现在给定两个0,1,2,...,n-1的排列p和q,求Perm((Ord(p)+Ord(q))%(n!)).


分析:

利用康托展开(参见 康托展开 - ACdreamer - 博客频道 - CSDN.NET),由于这里需要动态查询rank和order,需要使用数据结构维护,这里使用了pb_ds库中的平衡树,复杂度O(nlogn),也可以使用树状数组或者线段树+二分,复杂度O(n(logn)^2)。


代码:

#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<iostream>
#include<algorithm>
#include<ext/pb_ds/assoc_container.hpp>
#include<ext/pb_ds/tree_policy.hpp>
using namespace std;
using namespace __gnu_pbds;
typedef tree<int,null_type,less<int>,
            rb_tree_tag,tree_order_statistics_node_update> order_set;
int in[200005],cantor[3][200005];
order_set s;
order_set::iterator itr;
int main()
{
    int n;
    scanf("%d",&n);
    for(int i=0;i<n;i++)scanf("%d",&in[i]);
    s.clear();
    for(int i=n-1;i>=0;i--)
    {
        cantor[1][n-i-1]=s.order_of_key(in[i]);
        s.insert(in[i]);
    }
    for(int i=0;i<n;i++)scanf("%d",&in[i]);
    s.clear();
    for(int i=n-1;i>=0;i--)
    {
        cantor[2][n-i-1]=s.order_of_key(in[i]);
        s.insert(in[i]);
    }
    int up=0;
    for(int i=0;i<n;i++)
    {
        cantor[0][i]=(cantor[1][i]+cantor[2][i]+up)%(i+1);
        up=(cantor[1][i]+cantor[2][i]+up)/(i+1);
    }
    s.clear();
    vector<int>ans;
    for(int i=0;i<n;i++)s.insert(i);
    for(int i=n-1;i>=0;i--)
    {
        itr=s.find_by_order(cantor[0][i]);
        ans.push_back(*itr);
        s.erase(itr);
    }
    for(int i=0;i<ans.size();i++)
        printf("%s%d",(i>0 ? " " : ""),ans[i]);
    return 0;
}


猜你喜欢

转载自blog.csdn.net/quailty/article/details/46902225