Two kinds of achievements ways POJ 2299-Ultra-QuickSort- segment tree

There are two ways this question achievements!

Description

In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order.

For the input sequence
9 1 0 5 4 ,
Ultra-QuickSort produces the output
0 1 4 5 9 .

Your task is to determine how many swap operations Ultra-QuickSort needs to perform in order to sort a given input sequence.

Input

The input contains several test cases. Every test case begins with a line that contains a single integer n < 500,000 -- the length of the input sequence. Each of the the following n lines contains a single integer 0 ≤ a[i] ≤ 999,999,999, the i-th input sequence element. Input is terminated by a sequence of length n = 0. This sequence must not be processed.

Output

For every input sequence, your program prints a single line containing an integer number op, the minimum number of swap operations necessary to sort the given input sequence.

Sample Input

5
9
1
0
5
4
3
1
2
3
0

Sample Output

6
0

Subject to the effect:

Given an arrangement, this arrangement required number of reverse .

The definition of reverse

In one arrangement, if a pair of numbers in front and rear positions in reverse order size , i.e. the number greater than the number in front of the latter, they are called a reverse order.

main idea:

We structure for storing arrangement:
Here Insert Picture Description
A [i] .x i represents a numerical number, a [i] .id represents the i-th position.

For each number of a [i] .x, we find the position in front of it and a value larger than that of the number of the number of c [i], and c is the answer array.
Segment tree .
We count the number of times, the number to meet two conditions:
1, its position in front of
2, the value is bigger than its

us space and time to be separately controlled to satisfy the two conditions.
Space: the interval around the tree line .
Time: Update order segment tree .
So this question in two ways achievements ,

method one

From the space to be controlled to meet the position in front of it conditions;
the time is controlled to meet the greater than the value of its conditions.

Segment tree represents a section about the original position of the arrangement number , the left end section of the control query to meet the position in front of its conditions.
We will array a decreasing order of X , according to the new order are sequentially updated segment tree, a large value of the first entry (updates) segment tree , it is now a query tree from segment to satisfy a certain number of values larger than its condition .

This method does not require discrete achievements, the following approach requires discrete.

Second way

From the space to be controlled to meet the value is greater than its conditions;
the time is controlled to meet the position in front of its conditions.
Segment tree represents a section around the original value of the number of arrangement , by the left and right end sections of the control query to meet the numerical value is larger than its conditions.
We will a array by id in ascending order (i.e. the original sequence), the position of the first into the front (updated) segment tree , it is now a query tree from segment to satisfy a certain number of positions in front of its conditions.

NOTE : This number value range of the subject is 1e10, the length of a line segment tree as a value not to open such a large array. The solution is discrete .
Here Insert Picture Description
Discrete before and after the mapping function is:
Here Insert Picture Description

Range of values is the number of different discrete values , i.e. 5e5. This will open up an array of achievements.

A way Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e5+20;
char s[20];
//存原排列 
struct node{
    int x,id;
}a[N];
struct tnode{
    int l,r,sum;
}tr[N<<2];
void pushup(int m)
{
    tr[m].sum=tr[m<<1].sum+tr[m<<1|1].sum;
    return;
}
void build(int m,int l,int r)
{
    tr[m].l=l;
    tr[m].r=r;
    if(l==r)
    {
        tr[m].sum=0;
        return;
    }
    int mid=(l+r)>>1;
    build(m<<1,l,mid);
    build(m<<1|1,mid+1,r);
    pushup(m);
    return;
}
void update(int m,int x)
{
    if(tr[m].l==x&&tr[m].r==x)
    {
        tr[m].sum=1;
        return;
    }
    int mid=(tr[m].l+tr[m].r)>>1;
    if(x<=mid)
        update(m<<1,x);
    else
        update(m<<1|1,x);
    pushup(m);
    return;
}
int query(int m,int l,int r)
{
    if(tr[m].l==l&&tr[m].r==r)
        return tr[m].sum;
    int mid=(tr[m].l+tr[m].r)>>1;
    if(r<=mid)
        return query(m<<1,l,r);
    if(l>mid)
        return query(m<<1|1,l,r);
    return query(m<<1,l,mid)+query(m<<1|1,mid+1,r);
}
bool cmp(node p,node q)
{
    return p.x>q.x;
}
int main()
{
    int n;
    while(1)
    {
        scanf("%d",&n);
        if(!n)
            break;
        //根据n直接建树 
        build(1,1,n);
        //输入
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i].x);
            a[i].id=i;
        }
        //排序,x大的先进入线段树 
        sort(a+1,a+n+1,cmp);
        //边更新边查询 
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            ans+=query(1,1,a[i].id);
            update(1,a[i].id);
        }
        //输出 
        printf("%lld\n",ans);
    }
    return 0;
}

Second way Code:

#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long ll;
const int N=5e5+20;
int b[N],cnt;
//存原排列 
struct node{
    int x,id;
}a[N];
struct tnode{
    int l,r,sum;
}tr[N<<2];
void pushup(int m)
{
    tr[m].sum=tr[m<<1].sum+tr[m<<1|1].sum;
    return;
}
void build(int m,int l,int r)
{
    tr[m].l=l;
    tr[m].r=r;
    if(l==r)
    {
        tr[m].sum=0;
        return;
    }
    int mid=(l+r)>>1;
    build(m<<1,l,mid);
    build(m<<1|1,mid+1,r);
    pushup(m);
    return;
}
void update(int m,int x)
{
    if(tr[m].l==x&&tr[m].r==x)
    {
        tr[m].sum=1;
        return;
    }
    int mid=(tr[m].l+tr[m].r)>>1;
    if(x<=mid)
        update(m<<1,x);
    else
        update(m<<1|1,x);
    pushup(m);
    return;
}
int query(int m,int l,int r)
{
    if(tr[m].l==l&&tr[m].r==r)
        return tr[m].sum;
    int mid=(tr[m].l+tr[m].r)>>1;
    if(r<=mid)
        return query(m<<1,l,r);
    if(l>mid)
        return query(m<<1|1,l,r);
    return query(m<<1,l,mid)+query(m<<1|1,mid+1,r);
}
bool cmp1(node p,node q)
{
    return p.x<q.x;
}
bool cmp2(node p,node q)
{
    return p.id<q.id;
}
int getid(int x)
{
    return lower_bound(b,b+cnt,x)-b+1;
}
int main()
{
    int n;
    while(1)
    {
        scanf("%d",&n);
        if(!n)
            break;
        //输入 
        a[0].x=-1;
        for(int i=1;i<=n;i++)
        {
            scanf("%d",&a[i].x);
            a[i].id=i;
        }
        //先离散化 
        sort(a+1,a+n+1,cmp1);
        cnt=0;
        for(int i=1;i<=n;i++)
            if(a[i].x!=a[i-1].x)
                b[cnt++]=a[i].x;
        //根据离散后的cnt建树 
        build(1,1,cnt);
        //别忘了把a数组sort回来 
        sort(a+1,a+n+1,cmp2);
        //边更新边查询 
        ll ans=0;
        for(int i=1;i<=n;i++)
        {
            int t=getid(a[i].x);
            ans+=query(1,t,n);
            update(1,t);
        }
        //输出 
        printf("%lld\n",ans);
    }
    return 0;
}

Guess you like

Origin www.cnblogs.com/NothingbutFight/p/11306760.html