[复习]树状数组求逆序对 光荣的梦想
2017-10-12 19:04
405 查看
题目描述
Prince对他在这片大陆上维护的秩序感到满意,于是决定启程离开艾泽拉斯。在他动身之前,Prince决定赋予King_Bette最强大的能量以守护世界、保卫这里的平衡与和谐。在那个时代,平衡是个梦想。因为有很多奇异的物种拥有各种不稳定的能量,平衡瞬间即被打破。KB决定求助于你,帮助他完成这个梦想。
一串数列即表示一个世界的状态。
平衡是指这串数列以升序排列,而从一串无序数列到有序数列需要通过交换数列中的元素来实现。KB的能量只能交换相邻两个数字。他想知道他最少需要交换几次就能使数列有
4000
序。
输入格式
第一行为数列中数的个数 N(n≤100000)。
第二行为 N 个数a1~an(每个数小于100000),表示当前数列的状态。
输出格式
输出一个整数,表示最少需要交换几次能达到平衡状态。
样例数据
输入
4
2 1 4 3
输出
2
备注
本题另外一种描述:
给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目。
分析:树状数组求逆序对模板。代码比较难想,其实就是说每个数前面数的总数减去现在它前面小于它的数的个数,得到了大于它的数的个数,也就是逆序对数。
好吧,其实不难想,之前在想c[i]是干嘛用的,结果只是离散化了一下。这道题数据够小,不用c不sort直接把a往树状数组里放都可以(记得把数组开大)。
代码
本题结。
Prince对他在这片大陆上维护的秩序感到满意,于是决定启程离开艾泽拉斯。在他动身之前,Prince决定赋予King_Bette最强大的能量以守护世界、保卫这里的平衡与和谐。在那个时代,平衡是个梦想。因为有很多奇异的物种拥有各种不稳定的能量,平衡瞬间即被打破。KB决定求助于你,帮助他完成这个梦想。
一串数列即表示一个世界的状态。
平衡是指这串数列以升序排列,而从一串无序数列到有序数列需要通过交换数列中的元素来实现。KB的能量只能交换相邻两个数字。他想知道他最少需要交换几次就能使数列有
4000
序。
输入格式
第一行为数列中数的个数 N(n≤100000)。
第二行为 N 个数a1~an(每个数小于100000),表示当前数列的状态。
输出格式
输出一个整数,表示最少需要交换几次能达到平衡状态。
样例数据
输入
4
2 1 4 3
输出
2
备注
本题另外一种描述:
给定一个序列a1,a2,…,an,如果存在i<j并且ai>aj,那么我们称之为逆序对,求逆序对的数目。
分析:树状数组求逆序对模板。代码比较难想,其实就是说每个数前面数的总数减去现在它前面小于它的数的个数,得到了大于它的数的个数,也就是逆序对数。
好吧,其实不难想,之前在想c[i]是干嘛用的,结果只是离散化了一下。这道题数据够小,不用c不sort直接把a往树状数组里放都可以(记得把数组开大)。
代码
#include<iostream> #include<cstdio> #include<cstdlib> #include<cstring> #include<string> #include<ctime> #include<cmath> #include<algorithm> #include<cctype> #include<iomanip> #include<queue> #include<set> using namespace std; int getint() { int sum=0,f=1; char ch; for(ch=getchar();!isdigit(ch)&&ch!='-';ch=getchar()); if(ch=='-') { f=-1; ch=getchar(); } for(;isdigit(ch);ch=getchar()) sum=(sum<<3)+(sum<<1)+ch-48; return sum*f; } const int maxn=100010; struct node{ int c,pos; }a[maxn]; int n,sum[maxn],c[maxn]; long long ans; bool comp(const node &a,const node &b) { if(a.c==b.c) return a.pos<b.pos; return a.c<b.c; } int lowbit(int x) { return x & (-x); } void update(int x) { for(;x<=n;x+=lowbit(x)) sum[x]++; } int query(int x) { int res=0; for(;x>0;x-=lowbit(x)) res+=sum[x]; return res; } int main() { freopen("glory.in","r",stdin); freopen("glory.out","w",stdout); n=getint(); for(int i=1;i<=n;++i) a[i].c=getint(),a[i].pos=i; sort(a+1,a+n+1,comp); for(int i=1;i<=n;++i) c[a[i].pos]=i; for(int i=1;i<=n;++i) { update(c[i]); ans+=i-query(c[i]); } cout<<ans<<'\n'; return 0; }
本题结。
相关文章推荐
- [树状数组求逆序对]光荣的梦想
- 光荣的梦想 (树状数组求逆序数和)
- bzoj3295 动态逆序对【树状数组套权值线段树】
- E - Inversion-归并排序求逆序对/树状数组求逆序对
- 树状数组求逆序对个数
- POJ 2299 利用树状数组求逆序对数
- hdu 5497 Inversion 求逆序对 树状数组
- HDU 5792 World is Exploding (树状数组逆序对)
- poj 2299 树状数组求逆序数+离散化
- POJ 3067 Japan(树状数组:求逆序)
- “师创杯”山东理工大学第九届ACM程序设计竞赛 正式赛 I.皮卡丘的梦想2【树状数组】水题
- 【BZOJ3289】【莫队分块+树状数组求逆序对】Mato的文件管理
- POJ 3067 Japan(树状数组:求逆序)
- hdu 3743 Frosh Week (离散化+树状数组,求逆序对)
- POJ2299Ultra-QuickSort(归并排序 + 树状数组求逆序对)
- NYOJ 117 求逆序数 【树状数组】或【归并排序】
- 蓝桥杯小朋友排队(树状数组求逆序对)
- 逆序对(树状数组/归并)
- 树状数组求逆序对
- HDU 1394 Minimum Inversion Number (树状数组求逆序对)