codeforces #285 div2 D(康托,二分)

2015-01-12 22:17:45

思路:精简的好题。

  将两个排列的康托展开式的因子列出来,然后保存在数组中,相加的话满足大数加法+过程取模。这里因为数太多,所以需要用树状数组来维护比某个数小的数已经出现多少个。

  具体过程就是从第一个数开始,看它比多少个未出现的数大(这个值存数组),处理完两个排列后加起来。之后就是逆康托展开,用二分来搜索当前数该是几。

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <cstdlib>
 4 #include <cmath>
 5 #include <vector>
 6 #include <map>
 7 #include <set>
 8 #include <stack>
 9 #include <queue>
10 #include <iostream>
11 #include <algorithm>
12 using namespace std;
13 #define lp (p << 1)
14 #define rp (p << 1|1)
15 #define getmid(l,r) (l + (r - l) / 2)
16 #define MP(a,b) make_pair(a,b)
17 typedef long long ll;
18 typedef unsigned long long ull;
19 typedef pair<int,int> pii;
20 const int INF = (1 << 30) - 1;
21 const int maxn = 200010;
22 
23 ll n;
24 ll cof[maxn];
25 
26 struct BIT{
27     ll c[maxn];
28     void clear(){ memset(c,0,sizeof(c));}
29     ll Lowbit(ll x){ return x & -x;}
30     void Update(ll x,ll d){
31         while(x <= 200000){
32             c[x] += d;
33             x += Lowbit(x);
34         }
35     }
36     ll Getsum(ll x){
37         ll res = 0;
38         while(x){
39             res += c[x];
40             x -= Lowbit(x);
41         }
42         return res;
43     }
44 }T;
45 
46 ll Solve(ll val){
47     ll cur,mid,l = 1,r = n;
48     while(l < r){
49         mid = getmid(l,r);
50         cur = T.Getsum(mid);
51         if(cur >= val) r = mid;
52         else l = mid + 1;
53     }
54     T.Update(l,-1);
55     return l - 1;
56 }
57 
58 int main(){
59     ll t;
60     scanf("%I64d",&n);
61     T.clear();
62     for(ll i = 1; i <= n; ++i){
63         scanf("%I64d",&t);
64         cof[i] = t - T.Getsum(t + 1); //Cantor cof
65         T.Update(t + 1,1);
66     }
67     T.clear();
68     for(ll i = 1; i <= n; ++i){
69         scanf("%I64d",&t);
70         cof[i] += t - T.Getsum(t + 1);
71         T.Update(t + 1,1);
72     }
73     for(ll i = n; i >= 1; --i){
74         cof[i - 1] += cof[i] / (n - i + 1);
75         cof[i] %= n - i + 1;
76     }
77     for(ll i = 1; i <= n; ++i){
78         if(i > 1) printf(" ");
79         printf("%I64d",Solve(cof[i] + 1));
80     }
81     puts("");
82     return 0;
83 }

 

posted @ 2015-01-12 22:27  Naturain  阅读(169)  评论(0编辑  收藏  举报