您的位置:首页 > 产品设计 > UI/UE

poj 2299 Ultra-QuickSort

2013-04-27 17:31 337 查看
poj 2299 Ultra-QuickSort

结合各位大牛的博客后,终于完成了首题线段树的学习。

如有错误还望大牛们斧正。

#include<algorithm>
#include<cstdio>
#include<cstring>
#define L(t)(t<<1)
#define R(t)(t<<1|1)
#define Mid(a,b)((a+b)>>1)
using namespace std;

const int MAXN=500002;
struct Node
{
int l,r,val;
}tree[MAXN<<2];//结点数为4*N-1
struct node
{
int val,id;
}a[MAXN];
bool cmp(node a,node b)
{
return a.val>b.val;
}
int n,resort[MAXN];
//建树
void build(int l,int r,int root)//不断的递归,直到到达叶子结点开始回溯
{
tree[root].l=l;
tree[root].r=r;
tree[root].val=0;          //可以根据题目要求进行调整的值
if(r==l)return;           //当其为叶子是开始往父节点处递归(即开始往回回溯)
int m=Mid(l,r);
build(l,m,L(root));
build(m+1,r,R(root));
}
//更新
void modify(int l,int r,int root,int val)
{
if(tree[root].l==l&&tree[root].r==r)//要更新的点刚好在区间内,开始回溯
{
tree[root].val+=val;
return;
}
int m=Mid(tree[root].l,tree[root].r);
if(r<=m)                    //与左孩子有交集,考察左孩子
modify(l,r,L(root),val);
else if(l>m)                //与右孩子有交集,考察右孩子
modify(l,r,R(root),val);
else{                       //在左右两边跨集,分成两边进行考察
modify(l,m,L(root),val);
modify(m+1,r,R(root),val);
}
}
//查询
int query(int x,int root)         //插点问线
{
if(tree[root].l==tree[root].r)//递归结束条件,即已经找到叶子结点,开始回溯
return tree[root].val;
int m=Mid(tree[root].l,tree[root].r);
if(x<=m)                     //如果要询问的点,跟左孩子有交集,则考察左结点
return query(x,L(root))+tree[root].val;
else                        //考察右结点
return query(x,R(root))+tree[root].val;
}
//离散化处理
void discretization()
{
int i,temp=a[1].val,p=1;
for(i=1;i<=n;i++)
{
if(temp!=a[i].val)
{
a[i].val=++p;
temp=a[i].val;
}else
a[i].val=p;
}
for(i=1;i<=n;i++)
resort[a[i].id]=a[i].val;
}
int main()
{
while(scanf("%d",&n)&&n)
{
build(0,MAXN,1);
memset(resort,0,sizeof(resort));
for(int i=1;i<=n;i++)
{
scanf("%d",&a[i].val);
a[i].id=i;
}
sort(a+1,a+n+1,cmp);
discretization();
__int64 count=0;
for(int i=1;i<=n;i++)
{
count+=query(resort[i],1);
modify(resort[i],MAXN,1,1);
}
printf("%I64d\n",count);
}
return 0;
}


 

 
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: