Sherlock and Inversions CodeChef - IITI15

 

After a long series of jobless days, Sherlock and Watson frustated by the lack of new cases, decide to turn their minds toward something interesting like solving few logical problems. One of the problems they have to solve now is as follows:
Given an array A of size N and a list of Q number of queries, where each query has two numbers L and R, find for each query the number of inversions in the subarray from Lth to Rth position (both inclusive) of the array A( array has 1-based index).
For an array A two elements A[i] and A[j] form an inversion if A[i] > A[j] and i < j. Help them to solve this problem.

 

Input

  • First line contains a single integer, length N of the array.
  • Second line has N space separated numbers, where ith element is A[i].
  • Third line has a single integer Q.
  • Next Q lines have 2 space separated integers L and R of that query.

Output

  • Output Q lines, ith line having a single integer, the answer to the ith query

 

Constraints

  • 1N20000
  • 0A[i]10^9
  • 1Q20000
  • 1LRN

 

题解:莫队+树状数组,找每个区间的逆序对(i<j,a[i]>a[j]),用树状数组统计就行(BZOJ 3298,同一种做法)。

感受:每个元素对区间的贡献还没想明白!!!

懂了一点点,每个数的贡献是相对于原来的状态,即上一个ans而言,这里,加入一个数或者减少一个数,原来的逆序对会变化。

  1. 每次在最后添加一个数,比这个数大的数都会与其形成一个逆序对 
  2. 每次在最后移除一个数,比这个数大的数都会与其形成一个逆序对 
  3. 每次在最前添加一个数,比这个数小的数都会与其减少一个逆序对 
  4. 每次在最前移除一个数,比这个数小的数都会与其减少一个逆序对 ------------摘自https://www.cnblogs.com/zcysky/p/6847290.html
 1 #pragma warning(disable:4996)
 2 #include<cmath>
 3 #include<map>
 4 #include<cstdio>
 5 #include<cstring>
 6 #include<iostream>
 7 #include<algorithm>
 8 using namespace std;
 9 
10 const int maxn = 20005;
11 
12 int n, m, k, unit;
13 int a[maxn], bit[maxn], res[maxn], b[maxn];
14 
15 struct node { int l, r, id; } q[maxn];
16 
17 bool cmp(const node& a, const node& b) {
18     if (a.l / unit == b.l / unit) return a.r < b.r;
19     return a.l < b.l;
20 }
21 
22 void Inite() {
23     unit = sqrt(n);
24     memset(bit, 0, sizeof(bit));
25 }
26 
27 int sum(int i) {
28     int s = 0;
29     while (i > 0) {
30         s += bit[i];
31         i -= i & -i;
32     }
33     return s;
34 }
35 
36 void add(int i, int x) {
37     while (i <= n) {
38         bit[i] += x;
39         i += i & -i;
40     }
41 }
42 
43 int main()
44 {
45     while (scanf("%d", &n) != EOF) {
46         Inite();
47 
48         for (int i = 1; i <= n; i++) {
49             scanf("%d", &a[i]);
50             b[i] = a[i];
51         }
52 
53         sort(a + 1, a + n + 1);
54         k = unique(a + 1, a + n + 1) - (a + 1);
55 
56         map<int, int> p;
57         for (int i = 1; i <= k; i++) if (!p[a[i]]) p[a[i]] = i;
58 
59         scanf("%d", &m);
60         for (int i = 1; i <= m; i++) {
61             int u, v;
62             scanf("%d%d", &u, &v);
63             q[i].l = u;
64             q[i].r = v;
65             q[i].id = i;
66         }
67 
68         sort(q + 1, q + m + 1, cmp);
69 
70         int L = q[1].l, R = L - 1;
71         int ans = 0;
72         for (int i = 1; i <= m; i++) {
73             while (L < q[i].l) {
74                 ans -= sum(p[b[L]] - 1);
75                 add(p[b[L]], -1);
76                 L++;
77             }
78             while (L > q[i].l) {
79                 L--;
80                 ans += sum(p[b[L]] - 1);
81                 add(p[b[L]], 1);
82             }
83             while (R < q[i].r) {
84                 R++;
85                 ans += (R - L - sum(p[b[R]]));
86                 add(p[b[R]], 1);
87             }
88             while (R > q[i].r) {
89                 ans -= (R - L - sum(p[b[R]]) + 1);
90                 add(p[b[R]], -1);
91                 R--;
92             }
93             res[q[i].id] = ans;
94         }
95         for (int i = 1; i <= m; i++) printf("%d\n", res[i]);
96     }
97     return 0;
98 }

 

转载于:https://www.cnblogs.com/zgglj-com/p/8998527.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值