POJ2299题解
2019-12-28
Powered by Gauss
1.题目传送门:POJ2299
2.理解题意:
做题的时候,第一步也是最重要的就是理解题意。记住这句话。
POJ2299是一道标准的树状数组模板题。题意大致如下:
快速排序是一种非常优秀的排序方式,其精华在于循环比较和swap函数的应用。
先给你一个数N,表示这组数据(没错,这题是多组数据)数的个数,之后的N行,每行一个数Ai
请你输出在快速排序过程中经历的swap函数的次数。
3.算法思路:
树状数组是一种非常高效的数据结构,由于篇幅有限,这里不做讲解,作者将尽快写出一篇树状数组的稿子,敬请谅解。
树状数组的精华在于lowbit函数的使用,为了迎合题目,这里将query函数和update函数做了一些改动。
void update(int x,int k) { int i; for(i=x;i<=n;i=i+lowbit(i)) { tree[i]+=k; } }
int query(int x) { int i,sum=0; for(i=x;i>0;i=i-lowbit(i)) { sum+=tree[i]; } return sum; }
我们因为这道题的数据规模非常大,所以要用到一些离散化的思想。
for(i=1;i<=n;i++) { cin>>a[i].value; a[i].id=i; } sort(a+1,a+n+1,cmp); for(i=1;i<=n;i++) { a[i].pos=i; }
有了离散化,我们就可以大大降低时间复杂度了。
上面那段代码中,我们用结构体node来实现,包含三个参数,id,pos和value。
struct node { int id,value,pos; }a[500001];
最后,结合树状数组的计算模板,我们给出最后的AC源代码,用时3610MS:
#include#include #include #include using namespace std; int tree[500001],n; struct node { int id,value,pos; }a[500001]; int lowbit(int x) { return (x&(-x)); } void update(int x,int k) { int i; for(i=x;i<=n;i=i+lowbit(i)) { tree[i]+=k; } } int query(int x) { int i,sum=0; for(i=x;i>0;i=i-lowbit(i)) { sum+=tree[i]; } return sum; } int cmp(node a,node b) { return a.value<b.value; } int cmp1(node a,node b) { return a.id<b.id; } int main() { int i; long long sum; while(cin>>n && n) { sum=0; memset(tree,0,sizeof(tree)); for(i=1;i<=n;i++) { cin>>a[i].value; a[i].id=i; } sort(a+1,a+n+1,cmp); for(i=1;i<=n;i++) { a[i].pos=i; } sort(a+1,a+n+1,cmp1); for(i=1;i<=n;i++) { sum+=i-1-query(a[i].pos); update(a[i].pos,1); } cout< endl; } return 0; }
版权声明:知识产权神圣不可侵犯,这篇文章中的部分代码和思想源自:https://blog.csdn.net/weixin_43918531/article/details/87950037