题意是给你两个长度为$n$的排列,他们分别是$n$的第$a$个和第$b$个全排列。输出$n$的第$\left(a+b \right)\textrm{mod} \, n!$个全排列。

一种很容易的想法是直接把$a$和$b$求出来,然后计算$\left(a+b \right)\textrm{mod} \, n!$的值并直接求对应的排列,但是由于$n$的范围$\left(n\leq200000\right)$直接求值显然不可行。

因此,考虑全排列的康托展开(Cantor expansion) 任意一种排列在全排列中对应的序号为$$\sum_{i=1}^{n}{a}_{i}\times i!$$

于是,将输入的两个排列分别写成这种形式,然后遍历$n$相加,由于结果需要对$n!$取模,因此从最低位开始逐项将$a_i$加到$a_i+1$上去,最后将最高位的$a_n$模掉$n$即可。

之后,只要拟用康托展开即可求出对应的排列。

在实现过程中,由于需要维护"当前还没有使用过的第k大的数",因此可以用树状数组BIT维护。恢复排列时用树状数组+二分即可。

复杂度$\mathcal{O}({n\log}^{2}n )$

#include<iostream>
#include<cstring>
#include<string>
#include<cstdio>
#include<algorithm>
#include<cmath>
#define GETNUM(num) scanf("%d",&num)
#define IT_PT(BEG,END,TYPE,REG) copy(BEG,END,ostream_iterator<TYPE>(cout,REG))
#define CLR(ARR,NUM) memset(ARR,NUM,sizeof(ARR))
#define faster_io() ios_base::sync_with_stdio(false)
using namespace std;
const int MAXN = 200010;
int la[MAXN], lb[MAXN], a[MAXN], b[MAXN], f[MAXN], s[MAXN];
typedef int bit_type;
const int bit_maxn = MAXN;
int n;
int ff[MAXN];
bit_type tree[bit_maxn]; int lowbit(int x)
{
return x & (-x);
} void add(int x, int d)
{
x++;
while(x <= n) {
tree[x] += d;
x += lowbit(x);
}
} bit_type sum(int x)
{
x++;
bit_type ans = 0;
while(x) {
ans += tree[x];
x -= lowbit(x);
}
return ans;
}
int main()
{
cin >> n;
for(int i = 0; i < n; i++)
GETNUM(la[i]);
for(int i = 0; i < n; i++)
GETNUM(lb[i]);
CLR(tree, 0);
for(int i = 0; i < n; i++) {
add(i, 1);
}
for(int i = 0; i < n; i++) {
a[i] = sum(la[i] - 1);
add(la[i], -1);
}
CLR(tree, 0);
for(int i = 0; i < n; i++) {
add(i, 1);
}
for(int i = 0; i < n; i++) {
b[i] = sum(lb[i] - 1);
add(lb[i], -1);
s[i] = a[i] + b[i];
} CLR(tree, 0);
for(int i = 0; i < n; i++) {
add(i, 1);
ff[i] = 1;
}
for(int i = n - 1; i > 0; i--) {
s[i - 1] += s[i] / (n - i);
s[i] %= (n - i);
}
s[0] %= n;
int rr = n - 1;
for(int i = 0; i < n; i++) {
int r = rr;
int l = 0;
while(l < r) {
int mid = l + (r - l + 1) / 2;
int t = sum(mid - 1);
if(t <= s[i]) l = mid;
else r = mid - 1;
}
add(l, -1);
ff[l] = 0;
if(!i) {
printf("%d", l);
} else {
printf(" %d", l);
}
while(!ff[rr]) {
rr--;
}
}
return 0;
}

[Codeforces 501D] - Misha and Permutations Summation的更多相关文章

  1. Misha and Permutations Summation

    A - Misha and Permutations Summation 首先这个 mod n! 因为数量级上的差别最多只会对康拓展开的第一项起作用所以这个题并不需要把 ord (p) 和 ord ( ...

  2. 【codeforces 501D】Misha and Permutations Summation

    [题目链接]:http://codeforces.com/problemset/problem/501/D [题意] 给你两个排列; 求出它们的字典序num1和num2; 然后让你求出第(num1+n ...

  3. Codeforces Round #285 (Div.1 B & Div.2 D) Misha and Permutations Summation --二分+树状数组

    题意:给出两个排列,求出每个排列在全排列的排行,相加,模上n!(全排列个数)得出一个数k,求出排行为k的排列. 解法:首先要得出定位方法,即知道某个排列是第几个排列.比如 (0, 1, 2), (0, ...

  4. Codeforces Round #285 (Div. 1) B - Misha and Permutations Summation 康拓展开+平衡树

    思路:很裸的康拓展开.. 我的平衡树居然跑的比树状数组+二分还慢.. #include<bits/stdc++.h> #define LL long long #define fi fir ...

  5. CF501D Misha and Permutations Summation(康托展开)

    将一个排列映射到一个数的方法就叫做康托展开.它的具体做法是这样的,对于一个给定的排列{ai}(i=1,2,3...n),对于每个ai求有多少个aj,使得j>i且ai>aj,简单来说就是求a ...

  6. CodeForces 501B Misha and Changing Handles(STL map)

    Misha hacked the Codeforces site. Then he decided to let all the users change their handles. A user ...

  7. codeforces 501C. Misha and Forest 解题报告

    题目链接:http://codeforces.com/problemset/problem/501/C 题目意思:有 n 个点,编号为 0 - n-1.给出 n 个点的度数(即有多少个点跟它有边相连) ...

  8. Codeforces Round #337 Alphabet Permutations

    E. Alphabet Permutations time limit per test:  1 second memory limit per test:  512 megabytes input: ...

  9. codeforces 341C Iahub and Permutations(组合数dp)

    C. Iahub and Permutations time limit per test 1 second memory limit per test 256 megabytes input sta ...

随机推荐

  1. POJ 1321-棋盘问题(DFS 递归)

    POJ 1321-棋盘问题 K - DFS Time Limit:1000MS     Memory Limit:10000KB     64bit IO Format:%I64d & %I6 ...

  2. 计算广义积分$$\int_0^{+\infty}\cos x^p {\rm d}x,\int_0^{+\infty}\sin x^p {\rm d}x, p>1$$

    ${\bf 解:}$ 在角状域$G=\{z\in\mathbb{C}|0<{\rm Arg}z<\frac{\pi}{2p}\}$上引入辅助函数$e^{iz^p}$, 其中$z^p=|z| ...

  3. BZOJ 1059 矩阵游戏

    Description 小Q是一个非常聪明的孩子,除了国际象棋,他还很喜欢玩一个电脑益智游戏--矩阵游戏.矩阵游戏在一个\(N \times N\)黑白方阵进行(如同国际象棋一般,只是颜色是随意的). ...

  4. codeforces C. Sereja and Swaps

    http://codeforces.com/contest/426/problem/C 题意:找出连续序列的和的最大值,可以允许交换k次任意位置的两个数. 思路:枚举区间,依次把区间内的比较小的数换成 ...

  5. 模态运行EXE程序

    function ExecShowModal(APath: PChar; ACmdShow: Integer; ATimeout: Longword): Integer; var vStartupIn ...

  6. HttpWebRequest.GetResponse() raises exception when http status code 400 (bad request) is returned

    参考: .Net HttpWebRequest.GetResponse() raises exception when http status code 400 (bad request) is re ...

  7. java程序:set改造成map

    逻辑:       set是无序不重复数据元素的集合.       map是另一种set,如果将<key,value>看成一个整体的话,其实就是set.在map中,若用map的keyset ...

  8. 数据结构(线段树):BZOJ 1018: [SHOI2008]堵塞的交通traffic

    1018: [SHOI2008]堵塞的交通traffic Time Limit: 3 Sec  Memory Limit: 162 MBSubmit: 2638  Solved: 864 Descri ...

  9. 固定IP和绑定了MAC,可以在设置无线路由器供笔记本电脑和平板上网吗?

    固定IP和绑定了MAC,可以在设置无线路由器供笔记本电脑和平板上网吗? 这跟我们单位一样.很简单:首先要占一个 IP/MAC ,能上外网的,这首先要有,谁要肯给地址,我们这儿领导才有呢.我是网管,当然 ...

  10. Krypton Factor 困难的串-Uva 129(回溯)

    原题:https://uva.onlinejudge.org/external/1/129.pdf 按照字典顺序生成第n个“困难的串” “困难的串”指的是形如ABAB, ABCABC, CDFGZEF ...