[Codeforces 501D] - Misha and Permutations Summation
题意是给你两个长度为$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的更多相关文章
- Misha and Permutations Summation
A - Misha and Permutations Summation 首先这个 mod n! 因为数量级上的差别最多只会对康拓展开的第一项起作用所以这个题并不需要把 ord (p) 和 ord ( ...
- 【codeforces 501D】Misha and Permutations Summation
[题目链接]:http://codeforces.com/problemset/problem/501/D [题意] 给你两个排列; 求出它们的字典序num1和num2; 然后让你求出第(num1+n ...
- Codeforces Round #285 (Div.1 B & Div.2 D) Misha and Permutations Summation --二分+树状数组
题意:给出两个排列,求出每个排列在全排列的排行,相加,模上n!(全排列个数)得出一个数k,求出排行为k的排列. 解法:首先要得出定位方法,即知道某个排列是第几个排列.比如 (0, 1, 2), (0, ...
- Codeforces Round #285 (Div. 1) B - Misha and Permutations Summation 康拓展开+平衡树
思路:很裸的康拓展开.. 我的平衡树居然跑的比树状数组+二分还慢.. #include<bits/stdc++.h> #define LL long long #define fi fir ...
- CF501D Misha and Permutations Summation(康托展开)
将一个排列映射到一个数的方法就叫做康托展开.它的具体做法是这样的,对于一个给定的排列{ai}(i=1,2,3...n),对于每个ai求有多少个aj,使得j>i且ai>aj,简单来说就是求a ...
- 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 ...
- codeforces 501C. Misha and Forest 解题报告
题目链接:http://codeforces.com/problemset/problem/501/C 题目意思:有 n 个点,编号为 0 - n-1.给出 n 个点的度数(即有多少个点跟它有边相连) ...
- Codeforces Round #337 Alphabet Permutations
E. Alphabet Permutations time limit per test: 1 second memory limit per test: 512 megabytes input: ...
- codeforces 341C Iahub and Permutations(组合数dp)
C. Iahub and Permutations time limit per test 1 second memory limit per test 256 megabytes input sta ...
随机推荐
- 《C和指针》章节后编程练习解答参考——6.1
<C和指针>——6.1 6.1 题目: 编写一个函数,在一个字符串中进行搜索,查找另一子字符串中出现的字符. 函数原型如下: char *find_char(char const *sou ...
- 学习opencv 第六章 习题十三
用傅里叶变换加速卷积,直接上代码,Mat版是Copy他人的. CvMat版 #include "stdafx.h" #include "cv.h" #inclu ...
- shuffle机制和TextInputFormat分片和读取分片数据(九)
shuffle机制 1:每个map有一个环形内存缓冲区,用于存储任务的输出.默认大小100MB(io.sort.mb属性),一旦达到阀值0.8(io.sort.spill.percent),一个后台线 ...
- tomcat架构分析-索引
出处:http://gearever.iteye.com tomcat架构分析 (概览) tomcat架构分析 (容器类) tomcat架构分析 (valve机制) tomcat架构分析 (valve ...
- js和jsp
1.js中的字符串赋值可以用' '或者" ". alert('1111'); alert("1111"); document.getElementById('d ...
- Altium Designer 从导入DXF文件,并转换成板框
大多数人都知道,PADS中导入DXF文件,然后转换成板框,是很方便的.AD也同样可以做到. PADS导入DXF见:http://www.cnblogs.com/craftor/archive/2012 ...
- HDU 2255 奔小康赚大钱
题目分析:这个是个KM的模板题. #include<stdio.h> #include<string.h> #include<algorithm> #include ...
- 如何在svn系统中使用git
如果正在使用svn,打算换到git,又暂时不想放弃已有的svn代码库,可以选择git-svn.说一说我自己从svn到git的经验吧. 开始 安装最新版本的git,从git 1.5.3以后支持git-s ...
- 扩展KMP模板
注意:需要用特殊符号隔开 1 struct ExKmp{ void Init(){ memset(f,,sizeof(f)); memset(r,,sizeof(r)); } void Get_Fai ...
- 【模拟】Codeforces 710C Magic Odd Square
题目链接: http://codeforces.com/problemset/problem/710/C 题目大意: 构造一个N*N的幻方.任意可行解. 幻方就是每一行,每一列,两条对角线的和都相等. ...