bzoj 3289 : Mato的文件管理 (莫队+树状数组)
Posted kls123
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 3289 : Mato的文件管理 (莫队+树状数组)相关的知识,希望对你有一定的参考价值。
题目链接:
https://www.lydsy.com/JudgeOnline/problem.php?id=3289
思路:
求区间最小交换的次数将区间变成一个不降序列其实就是求区间逆序对的数量,这道题的样例解释可以不看,样例应该是
4和2换再和3换,这样就是最小的交换次数变成不降序列,从样例我们可以看出其实这就是求逆序对的过程,但是这道题是
区间询问逆序对的个数,我们需要离线处理所有询问,然后用树状数组维护数组中比这个数小的数的数量,用莫队逐个维护
就好了,
我们可以推出删除,增加一个数对当前区间逆序对数量变化的关系:
1. 在序列的前端添加一个数,那么序列逆序对的数量就会增加序列中比这个数小的数的数量
2.在序列的前端删除一个数,那么序列中逆序对的数量就会减少序列中比这个数小的数的数量
3.在序列的末端添加一个数,那么序列中逆序对的数量就会增加序列中比这个数大的数的数量
4.在序列的末端删除一个数,那么序列中逆序对的数量就会增加序列中比这个数大的数的数量
这里树状数组的作用就是维护序列中比某个数大/小的数的数量
实现代码;
#include<bits/stdc++.h> using namespace std; const int M = 1e5+10; int blo,n,m,a[M],b[M],c[M<<2],num[M]; int lowbit(int x){ return x&(-x);} int getsum(int x){ int sum = 0; while(x>0){ sum += c[x]; x -= lowbit(x); } return sum; } void update(int x,int val){ while(x <= n){ c[x] += val; x += lowbit(x); } } struct node{ int l,r,id; }q[M]; bool cmp(node a,node b){ if(a.l/blo == b.l/blo) return a.r < b.r; return a.l < b.l; } int main() { scanf("%d",&n); blo = sqrt(n); for(int i = 1;i <= n;i ++){ scanf("%d",&a[i]); b[i] = a[i]; } sort(b+1,b+n+1); for(int i = 1;i <= n;i ++) a[i] = lower_bound(b+1,b+1+n,a[i])-b; scanf("%d",&m); for(int i = 1;i <= m;i ++){ scanf("%d%d",&q[i].l,&q[i].r); q[i].id = i; } sort(q+1,q+1+m,cmp); int l = 1,r = 0,ans = 0; for(int i = 1;i <= m;i ++){ while(l < q[i].l) update(a[l],-1),ans -= getsum(a[l]-1),l++; while(r < q[i].r) r++,ans += getsum(n)-getsum(a[r]),update(a[r],1); while(l > q[i].l) l--,ans += getsum(a[l]-1),update(a[l],1); while(r > q[i].r) update(a[r],-1),ans -= getsum(n) - getsum(a[r]),r--; num[q[i].id] = ans; } for(int i = 1;i <= m;i ++) printf("%d ",num[i]); return 0; }
以上是关于bzoj 3289 : Mato的文件管理 (莫队+树状数组)的主要内容,如果未能解决你的问题,请参考以下文章