康托展开:现在给你一个长度为
排列,求这个排列在长度为
的所有排列中 是第几个排列(即求其排名)。
假设现在的排列是
那么排名等于
,其中
表示在剩余数组里面有多少个比
小的数的个数
例如排列
所以排列
的排名为
为什么加
,因为
这个式子求的是排列
前面有多少个排列,那么
的排名就需要加上
使用权值线段树解决:
,特判
的情况;然后将
删除掉,即
逆康托展开:现在给你排名
,求长度为
的排列中第
的排列是什么。
假设
,求第
个排列是什么
首先需要
减去
,那么
一开始排列为
同样使用权值线段树解决,处理第
个位置时,
,
;主要是如何求剩余数组里面第
个数,显然权值线段树基操,然后删除就是
总代码:
#include<bits/stdc++.h>
using namespace std;
#define endl '\n'
#define int long long
#define IOS ios::sync_with_stdio(false);cin.tie(NULL);cout.tie(NULL);
#define HelloWorld IOS;
const int N = 25;
struct Node{
int l, r;
int cnt;
}tr[4 * N];
int n, q, f[25];
void push_up(int u){
tr[u].cnt = (tr[u << 1].cnt + tr[u << 1 | 1].cnt);
}
void build(int u, int l, int r){
if(l == r) tr[u] = {l, r, 0};
else{
tr[u] = {l, r, 0};
int mid = (tr[u].l + tr[u].r) >> 1;
build(u << 1, l, mid);
build(u << 1 | 1, mid + 1, r);
}
}
void modify(int u, int pos, int v){
if(tr[u].l == pos && pos == tr[u].r) tr[u].cnt += v;
else{
int mid = (tr[u].l + tr[u].r) >> 1;
if(pos <= mid) modify(u << 1, pos, v);
else modify(u << 1 | 1, pos, v);
push_up(u);
}
}
int query_k(int u, int pos){
if(tr[u].l == tr[u].r) return tr[u].l;
else{
if(pos <= tr[u << 1].cnt) return query_k(u << 1, pos);
else return query_k(u << 1 | 1, pos - tr[u << 1].cnt);
}
}
int query_sum(int u, int l, int r){
if(l <= tr[u].l && tr[u].r <= r) return tr[u].cnt;
else{
int sum = 0;
int mid = (tr[u].l + tr[u].r) >> 1;
if(l <= mid) sum += query_sum(u << 1, l, r);
if(r > mid) sum += query_sum(u << 1 | 1, l, r);
return sum;
}
}
signed main(){
HelloWorld;
f[0] = 1;
for(int i = 1; i <= 20; i ++) f[i] = f[i - 1] * i;
cin >> n >> q;
build(1, 1, n);
while(q --){
char op; cin >> op;
if(op == 'P'){
int x; cin >> x;
x -= 1;
for(int i = 1; i <= n; i ++) modify(1, i, 1);
for(int i = 1; i <= n; i ++){
int sum = query_k(1, x / f[n - i] + 1);
cout << sum << " ";
x %= f[n - i];
modify(1, sum, -1);
}
cout << endl;
}
else{
vector<int> a(n + 1);
for(int i = 1; i <= n; i ++){
cin >> a[i];
modify(1, i, 1);
}
int ans = 0;
for(int i = 1; i <= n; i ++){
if(a[i] == 1) modify(1, 1, -1);
else{
int sum = query_sum(1, 1, a[i] - 1);
ans += sum * f[n - i];
modify(1, a[i], - 1);
}
}
cout << ans + 1 << endl;
}
}
return 0;
}



京公网安备 11010502036488号