CF 540E, 树状数组

Posted 茶杯

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了CF 540E, 树状数组相关的知识,希望对你有一定的参考价值。

题目大意:在1~10^9的范围内随便交换某些位置上的数,求逆序对数量,交换位置<=10^5

解:因为是交换位置很少,离散化来做,逆序对可以看成两部分,一部分是出现位置的逆序对,另一部分的出现了的数对于没有交换位置上的数(没有在离散化中出现的数)的逆序对。分别统计一下,第一part用树状数组,第二part之间算一下区间实际的数字和有多少个交换了位置的数字即可。

 

技术分享
 1 #include <cstdio>
 2 #include <iostream>
 3 #include <algorithm>
 4 #include <utility>
 5 #include <map>
 6 #include <string>
 7 #include <cmath>
 8 #include <vector>
 9 #include <cstring>
10 
11 using namespace std;
12 
13 #define SQR(x) ((x)*(x))
14 #define LL long long
15 #define LOWBIT(x) ((x)&(-(x)))
16 #define PB push_back
17 #define MP make_pair
18 
19 #define MAXN 211111
20 
21 struct TreeArray{
22     int tree[MAXN], n;
23     void clear(int nn = MAXN - 10) {
24         n = nn;
25         memset(tree, 0, sizeof(tree[0]) * (n + 10));
26     }
27     void add(int x, int num = 1) {
28         while (x <= n) {
29             tree[x] += num;
30             x += LOWBIT(x);
31         }
32     }
33     int get(int x) {
34         int res = 0;
35         while (x > 0) {
36             res += tree[x];
37             x -= LOWBIT(x);
38         }
39         return res;
40     }
41 } TA;
42 
43 pair<int, int > query[MAXN];
44 vector <int > lsh;
45 vector <int > a;
46 int n;
47 LL ans;
48 
49 void init() {
50     cin >> n;
51     int x, y;
52     lsh.clear();
53     for (int i = 0; i < n; ++i) {
54         cin >> x >> y;
55         query[i] = MP(x, y);
56         lsh.PB(x); lsh.PB(y);
57     }
58     sort(lsh.begin(), lsh.end()); 
59     lsh.erase(unique(lsh.begin(), lsh.end()), lsh.end());
60 }
61 
62 #define INDEX(x) ((lower_bound(lsh.begin(), lsh.end(), (x))-lsh.begin())+1)
63 
64 void solve() {
65     ans = 0;
66     a = lsh;
67     TA.clear(lsh.size()+10);
68     for (int i = 0; i < n; ++i) {
69 //        cout << query[i].first <<‘ ‘<< query[i].second << endl;
70         swap(a[INDEX(query[i].first)-1], a[INDEX(query[i].second)-1]);
71     }
72 
73 //    for (int i = 0; i < lsh.size(); ++i) cout << lsh[i] <<‘ ‘; cout << endl;
74 //    for (int i = 0; i < a.size(); ++i) cout << a[i] <<‘ ‘; cout << endl;
75 
76     for (int i = (int)a.size() - 1; i >= 0; --i) {
77         ans += TA.get(INDEX(a[i]) - 1);
78         TA.add(INDEX(a[i]));
79         int key = 0, t;
80         t = INDEX(a[i]) - 1;
81         if (i < t) {
82             key = (lsh[t] - lsh[i] - 1) - (t - i - 1);
83         } 
84         else {
85             key = (lsh[i] - lsh[t] - 1) - (i - t - 1);
86         }
87         ans += key;
88 //        cout << ans << endl;
89     }
90 }
91 
92 int main() {
93 //    freopen("test.txt", "r", stdin);
94     ios::sync_with_stdio(false);
95     init();
96     solve();
97     cout << ans << endl;
98     return 0;
99 }
CF 540E

 

以上是关于CF 540E, 树状数组的主要内容,如果未能解决你的问题,请参考以下文章

[CF369E]Valera and Queries_离线_树状数组

CF163E e-Government

CF869 E 二维BIT

CF1430E贪心树状数组

CF749E Inversions After Shuffle 解题报告 (期望 树状数组)

Codeforces Round #301 (Div. 2) E. Infinite Inversions —— 逆序对 离散化 + 树状数组