【BZOJ3289】Mato的文件管理(莫队算法+树状数组)
来源:互联网 发布:科沃斯 irobot 知乎 编辑:程序博客网 时间:2024/06/01 09:48
记录一个菜逼的成长。。
题目链接
题目要求交换次数,其实就是逆序数。
求逆序数,用树状数组来求。
题目没说数据范围,则离散化处理一下
考虑莫队算法
已知区间
1求[l,r+1] 的交换次数
假设
这个和一般的逆序数求法一样,更新树状数组,求和。
2求[l−1,r] 的交换次数
假设
因为区间的变化是区间的左端点往左移
所以每次加入一个,只要知道在这个区间里有多少个数比这个数小
所以
先求和
再更新
比如有序列
1 4 2 3
已知区间
树状数组的值为0 1 1 0
Rank[x] = 4 ,此时求和值为2,即有两个数比4小。
然后更新树状数组的值为0 1 1 1
3求[l,r−1] 的交换次数
假设
先更新
再减去相应的值
比如有序列
1 4 2 3
已知区间
树状数组的值为1 1 1 1
Ran[x] = 3,更新后树状数组的值为1 1 0 1
此时
4求[l+1,r] 的交换次数
假设
先更新
再减去相应的值
比如有序列
1 4 2 3
已知区间
树状数组的值为0 1 1 1
Rank[x] = 4,更新后树状数组的值为0 1 1 0
此时
#include <bits/stdc++.h>using namespace std;#define lowbit(x) (x)&(-x)#define cl(a,b) memset(a,b,sizeof(a))typedef long long LL;const int maxn = 50000 + 10;int pos[maxn],rk[maxn];struct Node{ int v,id;}a[maxn];bool cmp1(Node a,Node b){ if(a.v != b.v)return a.v < b.v; return a.id < b.id;}struct Query{ int l,r,id; int ans; bool operator < (const Query &a) const{ if(pos[l] != pos[a.l])return pos[l] < pos[a.l]; return r < a.r; }}Q[maxn];bool cmp2(Query a,Query b){ return a.id < b.id;}int c[maxn];void update(int x,int v){ while(x < maxn){ c[x] += v; x += lowbit(x); }}int getSum(int x){ int ret = 0; while(x > 0){ ret += c[x]; x -= lowbit(x); } return ret;}void solve(int n,int q){ cl(c,0); int ans = 0; int l = 1,r = 0; for( int i = 1; i <= q; i++ ){ if(r < Q[i].r){ for( r = r + 1; r < Q[i].r; r++ ){ update(rk[r],1); ans += getSum(maxn-1) - getSum(rk[r]); } update(rk[r],1); ans += getSum(maxn-1) - getSum(rk[r]); } if(l > Q[i].l){ for(l = l - 1; l > Q[i].l; l-- ){ ans += getSum(rk[l]); update(rk[l],1); } ans += getSum(rk[l]); update(rk[l],1); } if(r > Q[i].r){ for( ; r > Q[i].r; r-- ){ update(rk[r],-1); ans -= getSum(maxn-1) - getSum(rk[r]); } } if(l < Q[i].l){ for( ; l < Q[i].l; l++ ){ update(rk[l],-1); ans -= getSum(rk[l]); } } Q[i].ans = ans; } sort(Q+1,Q+1+q,cmp2); for( int i = 1; i <= q; i++ ) { printf("%d\n",Q[i].ans); }}int main(){ int n,q; while(~scanf("%d",&n)){ for( int i = 1; i <= n; i++ ){ scanf("%d",&a[i].v); a[i].id = i; } int k = sqrt(n); for( int i = 1; i <= n; i++ ){ pos[i] = (i-1) / k + 1;//分块 } sort(a+1,a+1+n,cmp1); for( int i = 1; i <= n; i++ ) rk[a[i].id] = i; scanf("%d",&q); for( int i = 1; i <= q; i++ ){ scanf("%d%d",&Q[i].l,&Q[i].r); Q[i].id = i; } sort(Q+1,Q+q+1);//对查询排序 solve(n,q); } return 0;}
- bzoj3289 Mato的文件管理 莫队算法 树状数组
- 【BZOJ3289】Mato的文件管理(莫队算法+树状数组)
- 【BZOJ3289】【莫队分块+树状数组求逆序对】Mato的文件管理
- [BZOJ3289]Mato的文件管理(莫队+树状数组)
- 【BZOJ3289】Mato的文件管理,莫队+树状数组
- 莫队+树状数组 题解【bzoj3289】Mato的文件管理
- bzoj3289 Mato的文件管理 莫队+树状数组
- [bzoj3289]Mato的文件管理 莫队+树状数组
- BZOJ3289 Mato的文件管理 【莫队 + 树状数组】
- [BZOJ3289] Mato的文件管理 && 莫队算法
- bzoj3289 Mato的文件管理 莫队算法
- 3289: Mato的文件管理 莫队算法+树状数组
- bzoj3289: Mato的文件管理
- bzoj3289 : Mato的文件管理
- Bzoj3289: Mato的文件管理
- [bzoj3289]Mato的文件管理
- bzoj3289 Mato的文件管理
- 【BZOJ3289】 Mato的文件管理
- java 正则表达式---未完 待续
- windows下redis安装、配置与简单使用
- JS操作数组循环删除指定元素,splice(i,1)出错解决方案
- 数制转换
- 莫队算法
- 【BZOJ3289】Mato的文件管理(莫队算法+树状数组)
- 仿系统闹钟,实现更新安装之后还可以响铃,开机启动功能需要手机自带开机自启动
- 高德地图坑爹的路线规划长度问题
- 知识点总结
- jquery操作input、select、checkbox、radio常用方法
- Java正则表达式入门
- Django从零开始搭建一个相册网站--3.基本视图映射
- 测量Dialog的宽度 高度
- Hadoop 3.0纠删码(Erasure Coding):节省一半存储空间