[BZOJ3289]Mato的文件管理(莫队+树状数组)
2016-04-26 17:04
549 查看
题目描述
传送门题解
一段区间内交换的最小次数就是这段区间内逆序对的个数,因为只要存在一个逆序对那么它们一定会交换。用权值树状数组动态维护逆序对,抓住”逆序对数=每一个数前面比它大的个数和=每一个数后面比它小的个数和“,再利用树状数组维护前缀和来搞。想好先统计再更新还是先更新再统计。
代码
#include<algorithm> #include<iostream> #include<cstring> #include<cstdio> #include<cmath> using namespace std; const int max_n=5e4+5; int n,m,cnt,t1,t2,ans; int b[max_n],p[max_n],a[max_n],num[max_n],C[max_n],final[max_n]; struct hp{int l,r,ln,rn,id;}q[max_n]; inline int cmp(int x,int y){return b[x]<b[y];} inline int cmp1(hp a,hp b){return a.ln<b.ln||a.ln==b.ln&&a.r<b.r;} inline void add(int loc,int val){ for (int i=loc;i<=n;i+=i&(-i)) C[i]+=val; } inline int query(int loc){ int ans=0; for (int i=loc;i>=1;i-=i&(-i)) ans+=C[i]; return ans; } int main(){ scanf("%d",&n); for (int i=1;i<=n;++i) scanf("%d",&b[i]),p[i]=i; sort(p+1,p+n+1,cmp); for (int i=1;i<=n;++i) if (b[p[i]]!=b[p[i-1]]) a[p[i]]=++cnt; else a[p[i]]=cnt; int t1=(int)sqrt(n); if (n%t1==0) t2=n/t1; else t2=n/t1+1; for (int i=1;i<=n;++i) if (i%t1==0) num[i]=i/t1; else num[i]=i/t1+1; scanf("%d",&m); for (int i=1;i<=m;++i){ scanf("%d%d",&q[i].l,&q[i].r); if (q[i].l>q[i].r) swap(q[i].l,q[i].r); q[i].ln=num[q[i].l]; q[i].rn=num[q[i].r]; q[i].id=i; } sort(q+1,q+m+1,cmp1); for (int i=q[1].r;i>=q[1].l;--i) ans+=query(a[i]-1),add(a[i],1); final[q[1].id]=ans; for (int i=2;i<=m;++i){ if (q[i-1].l>q[i].l) for (int j=q[i-1].l-1;j>=q[i].l;--j) ans+=query(a[j]-1),add(a[j],1); if (q[i-1].l<q[i].l) for (int j=q[i-1].l;j<q[i].l;++j) ans-=query(a[j]-1),add(a[j],-1); if (q[i-1].r<q[i].r) for (int j=q[i-1].r+1;j<=q[i].r;++j){ add(a[j],1); int k=query(a[j]); int len=j-q[i].l+1; ans+=len-k; } if (q[i-1].r>q[i].r) for (int j=q[i-1].r;j>q[i].r;--j){ int k=query(a[j]); int len=j-q[i].l+1; ans-=len-k; add(a[j],-1); } final[q[i].id]=ans; } for (int i=1;i<=m;++i) printf("%d\n",final[i]); }
总结
树状数组求逆序对要想好,细节比较蛋疼。相关文章推荐
- 如何在CentOS 7.x中安装OpenERP(Odoo)
- linux sed命令详解
- C/C++结构体的区别 C/C++结构体与类的区别
- WWW需要注意的问题
- Android 屏幕适配问题归纳
- C++使用TinyXML生成和解析xml文件
- c语言链表
- nopCommerce - 如何安装中文包
- linux系统编程之进程(一):进程与程序
- 刷新View的方法invalidate()手动调用onDraw()
- iOS 面试中单例模式的设计
- 2016随记
- 文字中间加横线效果
- 关于c语言学生宿舍管理系统
- 最长子串(长沙理工大学第十一届程序设计竞赛 离线 做了n天.....崩溃了)
- JS Range HTML文档/文字内容选中、库及应用介绍
- 高级语言程序设计作业
- ios返回上两级页面
- 使用nodejs搭建图片服务器(一)
- iscroll使用情况下click事件失效的问题