康托展开+线段树 Codeforces501D Misha and Permutations Summation

来源:互联网 发布:唐砖精校版txt下载知轩 编辑:程序博客网 时间:2024/04/27 21:40

传送门:点击打开链接

题意:求两个排列的次序相加取模n!后,得到新的次序,然后输出这个次序对应的排列

思路:康托展开+逆展开+高精度。康托展开其实是个求逆序对的过程,逆展开实际上是一个找第k大的过程,都可以使用线段树来完成

因为数字非常大,所以肯定是要用高精度的,但是这里的高精度很特别,不是使用十进制的高精度,而是使用阶乘进制的高精度,这样就可以和康托展开和逆展开完美的结合起来了。

#include<map>#include<set>#include<cmath>#include<ctime>#include<stack>#include<queue>#include<cstdio>#include<cctype>#include<string>#include<vector>#include<cstring>#include<iomanip>#include<iostream>#include<algorithm>#include<functional>#define fuck(x) cout<<"["<<x<<"]"#define FIN freopen("input.txt","r",stdin)#define FOUT freopen("output.txt","w+",stdout)using namespace std;typedef long long LL;typedef pair<int, int>PII;const int MX = 2e5 + 5;const int mod = 1e9 + 7;const int INF = 0x3f3f3f3f;#define lson l,m,rt<<1#define rson m+1,r,rt<<1|1int S[MX << 2], A[MX], B[MX], n;void push_up(int rt) {    S[rt] = S[rt << 1] + S[rt << 1 | 1];}void add(int x, int l, int r, int rt) {    if(l == r) {        S[rt]++; return;    }    int m = (l + r) >> 1;    if(x <= m) add(x, lson);    else add(x, rson);    push_up(rt);}int sum(int L, int R, int l, int r, int rt) {    if(L <= l && r <= R) return S[rt];    int m = (l + r) >> 1, ret = 0;    if(L <= m) ret += sum(L, R, lson);    if(R > m) ret += sum(L, R, rson);    return ret;}void build(int l, int r, int rt) {    if(l == r) {        S[rt] = 1; return;    }    int m = (l + r) >> 1;    build(lson); build(rson);    push_up(rt);}int query(int x, int l, int r, int rt) {    if(l == r) {        S[rt]--; return l;    }    int m = (l + r) >> 1, ret;    if(x <= S[rt << 1]) ret = query(x, lson);    else ret = query(x - S[rt << 1], rson);    push_up(rt);    return ret;}void Contor(int A[]) {    memset(S, 0, sizeof(S));    for(int i = 0; i < n; i++) {        int t; scanf("%d", &t); t++;        A[n - i - 1] = t - sum(1, t, 1, n, 1) - 1;        add(t, 1, n, 1);    }}void solve() {    build(1, n, 1); A[0] = 0;    for(int i = n - 1; i >= 0; i--) {        int x = query(A[i] + 1, 1, n, 1) - 1;        printf("%d%c", x, i == 0 ? '\n' : ' ');    }}int main() {    //FIN;    while(~scanf("%d", &n)) {        Contor(A); Contor(B);        for(int i = 1, t = 0; i < n; i++) {            A[i] += B[i] + t;            t = A[i] / (i + 1);            A[i] -= t * (i + 1);        }        solve();    }    return 0;}


0 0
原创粉丝点击