首页 > 代码库 > BZOJ 3289:Mato的文件管理(莫队算法+树状数组)
BZOJ 3289:Mato的文件管理(莫队算法+树状数组)
http://www.lydsy.com/JudgeOnline/problem.php?id=3289
题意:……
思路:求交换次数即求逆序对数。确定了这个之后,先离散化数组。然后在后面插入元素的话,就是在区间里面找比它大的元素数量,在前面插入元素的话,就是在区间里面找比它小的元素数量。删除操作类似。因为排序是从小到大排序,所以要找比它大的数量就是区间长度减去小于等于该元素的数量,所以是(R - L + 1 - sum(a[i])),要找比它小的数量就是(sum(a[i] - 1))。然后用莫队算法处理区间询问就好了。
1 #include <cstdio> 2 #include <cstring> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 #define N 50010 7 struct node { 8 int l, r, id, ans; 9 } p[N];10 int bit[N], a[N], b[N], num[N], ans, kuai, n;11 12 bool cmp(const node &a, const node &b) {13 if(a.l / kuai == b.l / kuai) return a.r < b.r;14 return a.l / kuai < b.l / kuai;15 }16 bool cmpid(const node &a, const node &b) { return a.id < b.id; }17 int lowbit(int x) { return x & (-x); }18 void add(int x, int w) { for( ; x <= n; x += lowbit(x)) bit[x] += w; }19 int sum(int x) { int ans = 0; for( ; x ; x -= lowbit(x)) ans += bit[x]; return ans; }20 21 int main() {22 while(~scanf("%d", &n)) {23 for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = a[i];24 int q; scanf("%d", &q);25 for(int i = 1; i <= q; i++) scanf("%d%d", &p[i].l, &p[i].r), p[i].id = i;26 27 memset(bit, 0, sizeof(bit));28 ans = 0; kuai = sqrt(n);29 sort(b + 1, b + 1 + n);30 int cnt = unique(b + 1, b + 1 + n) - b - 1;31 for(int i = 1; i <= n; i++) a[i] = lower_bound(b + 1, b + 1 + cnt, a[i]) - b;32 33 sort(p + 1, p + 1 + q, cmp);34 for(int L = 1, R = 0, i = 1; i <= q; i++) {35 int l = p[i].l, r = p[i].r;36 for( ; L < l; L++) { ans -= sum(a[L] - 1); add(a[L], -1); }37 for( ; L > l; L--) { ans += sum(a[L-1] - 1); add(a[L-1], 1); }38 for( ; R < r; R++) { ans += R - L + 1 - sum(a[R+1]); add(a[R+1], 1); }39 for( ; R > r; R--) { ans -= R - L + 1 - sum(a[R]); add(a[R], -1); }40 p[i].ans = ans;41 }42 sort(p + 1, p + 1 + q, cmpid);43 for(int i = 1; i <= q; i++) printf("%d\n", p[i].ans);44 }45 return 0;46 }
BZOJ 3289:Mato的文件管理(莫队算法+树状数组)
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。