当前位置: 代码迷 >> 综合 >> Codeforces 501D Misha and Permutations Summation (康托展开+平衡树优化)
  详细解决方案

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

热度:69   发布时间:2023-12-08 16:35:07.0

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;
}