POJ-2299(线段树或树状数组或归并排序)

博客详细介绍了如何使用线段树、归并排序和树状数组三种方法解决POJ-2299问题。线段树通过查询区间和更新节点来计算逆序数;归并排序中记录指针差值累加得到逆序数;树状数组则通过离散化数据,利用查询和更新功能找出比当前数字小的个数来计算逆序数。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

题目链接: Ultra-QuickSort

第一种解法(线段树)

思路

刚刚学线性代数学到的逆序数,用多重循环果然超时,刚开始的时候完全没有线段树的思路,后来看了别人的思路,发现真的妙啊,开心的飞起来,虽然我后面又因为把小括号写成中括号的问题WA了一晚上。比如说9 1 0 5 4这个序列,我们记录一下他们的序号位置,然后再排个序:

0 1 4 5 9
在原序列中的位置 3 2 5 4 1

开始我们把每个节点的数值都设置为1;
我们从最小数0开始看,他原来的位置是3,说明它前面比它大的有两个数,我们查询从1到(位置-1),也就是1到2,查询这段区间的总和为2;然后我们把这个位置的和-1,再依次往后看次小数。我们把所有查询的数字加起来就是总的逆序数了。

#include <cstdio>
#include <iostream>
#include <algorithm>
#include <cstring>
using namespace std;
const int inf=0x3f3f3f3f;
const int maxn=500001;
int addmark[maxn<<2],seqtree[maxn<<2];
struct node{
   
   
     int value,id;
}a[maxn];
int cmp(node a,node b)
{
   
   
    return a.value<b.value;
}
void maketree(int node,int begin,int end)
{
   
   
    if(begin==end)
    {
   
   
        seqtree[node]=1;
        return;
    }
    int mid=(begin+end)/2;
    maketree(node<<1,begin,mid);
    maketree(node<<1|1,mid+1,end);
    seqtree[node]=seqtree[node<<1]+seqtree[node<<1|1];
}
void update(int node,int begin,int end,int pos,int grade)
{
   
   
    if(pos<begin || pos>end)
        return;
    if(begin==end && begin==pos)
    {
   
   
        seqtree[node]+=grade;
        return;
    }
    int mid=(begin
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值