BZOJ3289 Mato的文件管理

好烦的题,做了我2h,看来蒟蒻就是弱啊。。。

感觉就是莫队算法来着,然后就走上了乱搞的不归路、、、

莫队算法详情请上百度搜索,谢谢!>.<

这道题要求逆序对,所以可以用树状数组动态维护。每次转移复杂度就是树状数组点修改的复杂度,但是转移的时候好烦。。。(一定是我太弱了)

再加上分块,总复杂度为O(n * sqrt(n) * log(n)),刚刚好卡过去。。。

  1 /**************************************************************
  2     Problem: 3289
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:8772 ms
  7     Memory:10200 kb
  8 ****************************************************************/
  9
 10 #include <cstdio>
 11 #include <cmath>
 12 #include <algorithm>
 13
 14 using namespace std;
 15 typedef long long LL;
 16
 17 struct data{
 18     int l, r, wl, w;
 19     LL ans;
 20 } a[150000];
 21 inline bool cmp(data a, data b){
 22     return a.wl == b.wl ? a.r < b.r : a.l < b.l;
 23 }
 24
 25 inline bool cmp_id(data a, data b){
 26     return a.w < b.w;
 27 }
 28
 29 LL x[150000], y[150000];
 30 LL BIT[150000], rank[150000];
 31 int TOT, T, tot, w[150000], block[150000];
 32 int n, Q, l, r, num;
 33 LL sum;
 34
 35 void build(){
 36     T = (int) sqrt(n), tot = 0;
 37     int x = 0;
 38     while (x < n)
 39         x += T, w[++tot] = x;
 40     w[tot] = min(w[tot], n);
 41     int y = 1;
 42     for (int i = 1; i <= n; ++i)
 43         if (i <= w[y]) block[i] = y;
 44         else block[i] = ++y;
 45 }
 46
 47 inline int lowbit(int x){
 48     return x & (-x);
 49 }
 50
 51 LL query(int x){
 52     if (x < 0) return 0;
 53     LL res = 0;
 54     while (x)
 55         res += BIT[x], x -= lowbit(x);
 56     return res;
 57 }
 58
 59 void change(int x, int del){
 60     while (x <= n)
 61         BIT[x] += del, x += lowbit(x);
 62 }
 63
 64 void update_right(int p, int del){
 65     sum += (LL) del * (num - query(x[p])), num += del;
 66     change(x[p], del);
 67 }
 68
 69 void update_left(int p, int del){
 70     change(x[p], del);
 71     sum += (LL) del * query(x[p] - 1), num += del;
 72 }
 73
 74 int find(int x){
 75     int l = 1, r = TOT, mid;
 76     for (; l != r; ){
 77         mid = (l + r) >> 1;
 78         if (rank[mid] >= x) r = mid;
 79         else l = mid + 1;
 80     }
 81     return l;
 82 }
 83
 84 int main(){
 85     scanf("%d", &n);
 86     for (int i = 1; i <= n; ++i){
 87         scanf("%lld", x + i);
 88         y[i] = x[i];
 89     }
 90     build();
 91     sort(y + 1, y + n + 1);
 92     rank[++TOT] = y[1];
 93     for (int i = 2; i <= n; ++i)
 94         if (y[i] != y[i - 1])
 95             rank[++TOT] = y[i];
 96     for (int i = 1; i <= n; ++i)
 97         x[i] = find(x[i]);
 98
 99     scanf("%d", &Q);
100     for (int i = 1; i <= Q; ++i){
101         scanf("%d%d", &a[i].l, &a[i].r);
102         a[i].wl = block[a[i].l], a[i].w = i;
103     }
104     sort(a + 1, a + Q + 1, cmp);
105     l = 1, r = 0, num = sum = 0;
106     for (int i = 1; i <= Q; ++i){
107         for (; r < a[i].r; ++r) update_right(r + 1, 1);
108         for (; r > a[i].r; --r) update_right(r, -1);
109         for (; l < a[i].l; ++l) update_left(l, -1);
110         for (; l > a[i].l; --l) update_left(l - 1, 1);
111         a[i].ans =  a[i].l == a[i].r ? 0 : sum;
112     }
113
114     sort(a + 1, a + Q + 1, cmp_id);
115     for (int i = 1; i <= Q; ++i)
116         printf("%lld\n", a[i].ans);
117     return 0;
118 }

时间: 2024-10-26 03:09:36

BZOJ3289 Mato的文件管理的相关文章

数据离散化 ( 以及 stl 中的 unique( ) 的用法 )+ bzoj3289:Mato的文件管理

http://blog.csdn.net/gokou_ruri/article/details/7723378 ↑惯例Mark大神的博客 bzoj3289:Mato的文件管理 线段树求逆序对+莫队,但是数据量50000却没有给出范围,既然求逆序对,那么我们关注的只是数据之间的相对大小,此时我们可以把这50000个数据进行简化...嗯看大神的博客就明白了不需要多解释什么了..   下面是博客中未授权截取的大神的代码板子....不过都是自己看应该也没什么吧..... sort(sub_a,sub_a

[bzoj3289]Mato的文件管理_莫队_树状数组

Mato的文件管理 bzoj-3289 题目大意:给定一个n个数的序列.m次询问:一段区间中的逆序对个数. 注释:$1\le n\,mle 5\cdot 10^4$. 想法: 开始想这个题的大佬们,给您点儿提示吧:$O(nlogn\sqrt(n))$可过哦! 所以这个题就是莫队的裸题了. 我们的莫队上的区间在动的时候随时更新树状数组上的信息即可.. 然后碰见了一整块区间,我们就直接求逆序对即可, 最后,附上丑陋的代码... ... #include <iostream> #include &l

【莫队算法】bzoj3289 Mato的文件管理

莫队算法,离线回答询问,按一定大小(sqrt(n*log(n))左右)将答案分块,按 ①左端点所在块②右端点 双关键字排序. 然后暴力转移. 转移的时候用树状数组. O(n*sqrt(n)*log(n)). 注意:①在一列数的后面添加一个数,逆序对数会增加 数列中比它大的数的个数. ②在一列数的后面删除一个数,逆序对数会减少 数列中比它大的数的个数. ③在一列数的前面添加一个数,逆序对数会增加 数列中比它小的数的个数. ④在一列数的前面删除一个数,逆序对数会减少 数列中比它小的数的个数. 1 #

BZOJ3289——Mato的文件管理

1.题意:排序交换的次数就是逆序对的个数,所以就是求区间逆序对 2.分析:本蒟蒻太垃圾,不会在线做法,直接离线了,思考一下逆序对的求法,跑一边树状数组就好,那么我们使用莫队算法,每次转移的时候就按照这个点对答案的贡献,然后把贡献减掉就行了,时间复杂度O(nn√logn) #include <cmath> #include <cstdio> #include <cstdlib> #include <cstring> #include <algorithm

【BZOJ3289】Mato的文件管理 莫队算法+树状数组

[BZOJ3289]Mato的文件管理 Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.Mato有一个习惯,他总是从文件大小从小到大看资料.他先把要看的文件按编号顺序依次拷贝出来,再用他写的排序程序给文件大小排序.排序程序可以在1单位时间内交换2个相邻的文件(因为加密

【bzoj3289】Mato的文件管理

3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MB Submit: 1056  Solved: 464 [Submit][Status][Discuss] Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.M

BZOJ 3289: Mato的文件管理[莫队算法 树状数组]

3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MBSubmit: 2399  Solved: 988[Submit][Status][Discuss] Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.Mat

BZOJ 3289 Mato的文件管理(莫队+离散化求逆序数)

3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MB Submit: 2171  Solved: 891 [Submit][Status][Discuss] Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.M

bzoj 3289: Mato的文件管理 莫队+树状数组

3289: Mato的文件管理 Time Limit: 40 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Mato同学从各路神犇以各种方式(你们懂的)收集了许多资料,这些资料一共有n份,每份有一个大小和一个编号.为了防止他人偷拷,这些资料都是加密过的,只能用Mato自己写的程序才能访问.Mato每天随机选一个区间[l,r],他今天就看编号在此区间内的这些资料.Mato有一个习惯,他总是从文件大小从小到大看资料.他先