萌新求问

P1908 逆序对

hytallenxu @ 2024-05-10 18:15:22

先开始心血来潮,想用 treap 来写在线的逆序对,但是发现了打了上去只有30分。

后面发现是数据里面有重复的元素,导致treap的排名函数出了问题。

比如说:

2
1 1

我的 treap 输出 1,很显然是不对的。

原因就在于 treap 排名的定义是排名定义为比当前数小的数的个数 +1,导致重复元素都会当做同一个排名来看待。

请问有什么方法可以解决这个问题?


by daiyulong2024 @ 2024-05-10 18:17:02

@hytallenxu 树状数组或线段树或归并排序。

//树状数组做法
#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
vector<ll> a(1),c,ls(1);
ll n,ans,x;
ll lowbit(ll x) {
    return x&-x;
}
void add(int id,ll x) {
    for(int i=id;i<=n;i+=lowbit(i)) {
        c[i]+=x;
    }
}
ll getsum(ll x) {
    int sum=0;
    for(int i=x;i;i-=lowbit(i)) {
        sum+=c[i];
    }
    return sum;
}
int main() {
    cin>>n;
    c.resize(n+5);
    for(int i=1;i<=n;i++) {
        cin>>x;
        a.push_back(x),ls.push_back(x); 
    }
    sort(ls.begin()+1,ls.end());
    for(int i=1;i<=n;i++) {
        a[i]=lower_bound(ls.begin()+1,ls.end(),a[i])-ls.begin()+1;
    }
    for(int i=n;i>=1;i--) {
        ans+=getsum(a[i]-1);
        add(a[i],1);
    }
    cout<<ans;
    return 0;
}

by daiyulong2024 @ 2024-05-10 18:17:23

@hytallenxu 别忘了加离散化。


by hytallenxu @ 2024-05-10 18:19:25

@daiyulong2024 我知道,但就是想问treap怎么做。


by _fairytale_ @ 2024-05-11 11:58:37

@hytallenxu 将下标也作为关键字比较即可,一个偷懒的办法是把值都变成它乘上 100000 加下标。


by _fairytale_ @ 2024-05-11 11:59:23

哦应该是 500000


by hytallenxu @ 2024-05-11 20:17:09

@fairytale 按您这个方法爆0了 Record


by _fairytale_ @ 2024-05-11 20:50:45

@hytallenxu 开 long long 就过了


by hytallenxu @ 2024-05-11 21:50:23

@fairytale ok thx


|