POJ 2299 Ultra-QuickSort(线段树+离散化)

题目地址:POJ 2299

这题曾经用归并排序做过,线段树加上离散化也可以做。一般线段树的话会超时。

这题的数字最大到10^10次方,显然太大,但是可以利用下标,下标总共只有50w。可以从数字大的开始向树上加点,然后统计下标比它小即在它左边的数的个数。因为每加一个数的时候,比该数大的数已经加完了,这时候坐标在它左边的就是一对逆序数。

但是该题还有一个问题,就是数字重复的问题。这时候可以在排序的时候让下标大的在前面,这样就可以保证加点的时候下标比他小的数中不会出现重复的。

这题需要注意的是要用__int64。

代码如下:

#include <iostream>
#include <cstdio>
#include <string>
#include <cstring>
#include <stdlib.h>
#include <math.h>
#include <ctype.h>
#include <queue>
#include <map>
#include <set>
#include <algorithm>

using namespace std;
#define LL __int64
#define lson l, mid, rt<<1
#define rson mid+1, r, rt<<1|1
LL sum[2100000];
struct node
{
    LL x, id;
} fei[600000];
bool cmp(node x, node y)
{
    if(x.x==y.x)
        return x.id>y.id;
    return x.x>y.x;
}
void PushUp(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
}
void update(LL x, int l, int r, int rt)
{
    if(l==r)
    {
        sum[rt]++;
        return ;
    }
    int mid=l+r>>1;
    if(x<=mid) update(x,lson);
    else update(x,rson);
    PushUp(rt);
}
LL query(int ll, int rr, int l, int r, int rt)
{
    if(ll<=l&&rr>=r)
    {
        return sum[rt];
    }
    LL ans=0;
    int mid=l+r>>1;
    if(ll<=mid) ans+=query(ll,rr,lson);
    if(rr>mid) ans+=query(ll,rr,rson);
    return ans;
}
int main()
{
    int n, i, j;
    LL ans;
    while(scanf("%d",&n)!=EOF&&n)
    {
        memset(sum,0,sizeof(sum));
        for(i=1; i<=n; i++)
        {
            scanf("%I64d",&fei[i].x);
            fei[i].id=i;
        }
        sort(fei+1,fei+n+1,cmp);
        ans=0;
        for(i=1; i<=n; i++)
        {
            ans+=query(1,fei[i].id,1,n,1);
            update(fei[i].id,1,n,1);
        }
        printf("%I64d\n",ans);
    }
    return 0;
}

POJ 2299 Ultra-QuickSort(线段树+离散化)

时间: 2024-08-09 20:40:36

POJ 2299 Ultra-QuickSort(线段树+离散化)的相关文章

POJ - 2528 - Mayor&#39;s posters 【线段树+离散化+补点】

http://poj.org/problem?id=2528 #include <cstdio> #include <iostream> #include <set> #include <cstring> #include <string> #define left rt<<1 #define right rt<<1|1 using namespace std; const int MAXN = 32768 + 5; in

Poj 2528 Mayor&#39;s posters (线段树+离散化)

题目连接: http://poj.org/problem?id=2528 题目大意: 有10000000块瓷砖,n张海报需要贴在墙上,每张海报所占的宽度和瓷砖宽度一样,长度是瓷砖长度的整数倍,问按照所给海报顺序向瓷砖上贴海报,最后有几张海报是可见的? 解题思路: 因为瓷砖块数和海报张数多,首选线段树,如果按照常规的建树方式,把瓷砖当做数的节点,肯定会MTL......... 所以我们可以用海报的起点和终点当做树的节点,这样树的节点才有20000个,但是这样建树的话,求海报覆盖了那些节点会很复杂,

POJ 2528 (线段树+离散化) Mayor&#39;s posters

因为将每个单位都作为一个最小单元的话会爆内存的 所以,将海报的每个端点进行排序,将这些端点最为最小的区间. 毕竟是刚刚接触线段树,理解起来还有些吃力,还是那句话,题做多了慢慢就好了. 萌萌的AC代码君贴上. 1 //#define LOCAL 2 #include <iostream> 3 #include <algorithm> 4 #include <cmath> 5 using namespace std; 6 7 int n; 8 struct CPost 9

POJ 2482 Stars in Your Window 线段树+离散化+扫描线

题面据说很美- 每个星星可以根据在窗口的左下角和右上角两个位置建立两条扫描线,之后就是简单的区间增减和求最大值操作了. 注意要处理在边界上的星星是不算的情况,其实只要把左右边界分别增减一个eps即可. #include <cstdio> #include <cstring> #include <iostream> #include <map> #include <set> #include <vector> #include <

【POJ】 2528 - Mayor&#39;s posters 【线段树+离散化】

题目: Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 47228   Accepted: 13719 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing their electoral

【POJ 2482】 Stars in Your Window(线段树+离散化+扫描线)

[POJ 2482] Stars in Your Window(线段树+离散化+扫描线) Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 11294   Accepted: 3091 Description Fleeting time does not blur my memory of you. Can it really be 4 years since I first saw you? I still remembe

D - Mayor&#39;s posters (线段树+离散化处理) POJ 2528

D - Mayor's posters Time Limit:1000MS Memory Limit:65536KB 64bit IO Format:%I64d & %I64u Submit Status Practice POJ 2528 Description The citizens of Bytetown, AB, could not stand that the candidates in the mayoral election campaign have been placing

POJ 2528 Mayor&#39;s posters(线段树+离散化)

题目链接:Mayor's posters 题意:按顺序往墙上贴海报,可以重叠,问最后可以看到多少海报.(被覆盖的海报是看不到的) 注意: 因为数据比较大,所以不离散化,肯定爆内存. 还有就是,不能只是单纯的离散化,还要处理好点的边界 举个例子 4 2  10. 2  8 3  6 6  8 8  10 离散化后 2 3 6 8 10 1 2 3 4 5 覆盖掉了 1 5   和  1 4俩段 只剩下 2  3  .3  4. 4  5 答案是 3 但是正确答案是4 所以,离散化处理时要处理边界,

POJ 3277 City Horizon(线段树+扫描线+离散化)

题目地址:POJ 3277 水题..稍微处理一下然后用求面积并的方法求即可. 代码如下: #include <iostream> #include <cstdio> #include <string> #include <cstring> #include <stdlib.h> #include <math.h> #include <ctype.h> #include <queue> #include <