BZOJ 3289: Mato的文件管理
3289: Mato的文件管理
Time Limit: 40 Sec Memory Limit: 128 MBSubmit: 2368 Solved: 971
[Submit][Status][Discuss]
Description
Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号。为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问。Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料。Mato有一个习惯,他总是从文件大小从小到大看资料。他先把要看的文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序。排序程序可以在1单位时间内交换2个相邻的文件(因为加密需要,不能随机访问)。Mato想要使文件交换次数最小,你能告诉他每天需要交换多少次吗?
Input
第一行一个正整数n,表示Mato的资料份数。
第二行由空格隔开的n个正整数,第i个表示编号为i的资料的大小。
第三行一个正整数q,表示Mato会看几天资料。
之后q行每行两个正整数l、r,表示Mato这天看[l,r]区间的文件。
Output
q行,每行一个正整数,表示Mato这天需要交换的次数。
Sample Input
4
1 4 2 3
2
1 2
2 4
1 4 2 3
2
1 2
2 4
Sample Output
0
2
2
HINT
Hint
n,q <= 50000
样例解释:第一天,Mato不需要交换
第二天,Mato可以把2号交换2次移到最后。
Source
小生的第二道莫队算法。易知一段区间内的最小交换次数就是这段区间内的逆序对数,这个可以通过用树状数组动态维护。树状数组是按权值组织的,当在区间右侧新加入一个元素时,新形成的逆序对数就是前面区间中严格大于该元素的元素个数,反之亦然,请客官自行推导吧(ノ*・ω・)ノ。
1 #include <bits/stdc++.h> 2 3 template <class T> 4 inline void read(T &num) { 5 register int neg = false; 6 register int bit = getchar(); 7 8 while (bit <= '0') { 9 if (bit == '-') 10 neg ^= neg; 11 bit = getchar(); 12 } 13 14 num = 0; 15 16 while (bit >= '0') { 17 num = num*10 18 + bit - '0'; 19 bit = getchar(); 20 } 21 22 if (neg)num = -num; 23 } 24 25 const int siz = 50005; 26 27 int n, m, s, num[siz], tmp[siz], bit[siz], answer; 28 29 struct query { 30 int l, r, id, ans; 31 }qry[siz]; 32 33 inline bool cmp_lr(const query &A, const query &B) { 34 if (A.l / s != B.l / s) 35 return A.l < B.l; 36 else 37 return A.r < B.r; 38 } 39 40 inline bool cmp_id(const query &A, const query &B) { 41 return A.id < B.id; 42 } 43 44 inline void add(int k, int v) { 45 for (; k <= n; k += k&-k)bit[k] += v; 46 } 47 48 inline int ask(int k) { 49 int ret = 0; 50 for (; k >= 1; k -= k&-k)ret += bit[k]; 51 return ret; 52 } 53 54 signed main(void) { 55 read(n); 56 57 for (int i = 1; i <= n; ++i) 58 read(num[i]); 59 60 memcpy(tmp, num, sizeof(tmp)); 61 62 std::sort(tmp + 1, tmp + 1 + n); 63 64 int tot = std::unique(tmp + 1, tmp + 1 + n) - tmp; 65 66 for (int i = 1; i <= n; ++i) 67 num[i] = std::lower_bound(tmp, tmp + tot, num[i]) - tmp; 68 69 read(m); 70 71 for (int i = 1; i <= m; ++i) 72 read(qry[i].l), read(qry[i].r), qry[i].id = i; 73 74 s = sqrt(n); 75 76 std::sort(qry + 1, qry + 1 + m, cmp_lr); 77 78 for (int i = 1, x = 1, y = 0; i <= m; ++i) { 79 while (x < qry[i].l)answer -= ask(num[x] - 1), add(num[x], -1), ++x; 80 while (x > qry[i].l)--x, answer += ask(num[x] - 1), add(num[x], +1); 81 while (y < qry[i].r)++y, answer += ask(n) - ask(num[y]), add(num[y], +1); 82 while (y > qry[i].r)answer -= ask(n) - ask(num[y]), add(num[y], -1), --y; 83 qry[i].ans = answer; 84 } 85 86 std::sort(qry + 1, qry + 1 + m, cmp_id); 87 88 for (int i = 1; i <= m; ++i) 89 printf("%d\n", qry[i].ans); 90 }
@Author: YouSiki