|poj 2299|权值线段树|Ultra-QuickSort

poj 2299
注意开long long
权值线段树就是线段树每个节点存每个权值出现的次数,本题求逆序对应该算一个比较简单的权值线段树,注意离散化

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<vector>
#include<queue>
using namespace std;
#define ms(i, j) memeset(i, j, sizeof i)
#define LL long long
const int MAXN = 500000 + 5;

int n;
int a[MAXN], sa[MAXN], siz;
int sumv[MAXN * 4];
#define M ((l+r)>>1)
#define lc o*2
#define rc o*2+1
void pushup(int o) {
    sumv[o] = sumv[lc] + sumv[rc];
}
void update(int o, int l, int r, int p) {
    if (l==r) {
        sumv[o]++;
        return ;
    }
    if (p<=M) update(lc,l,M,p); else if (M<p) update(rc,M+1,r,p); 
    pushup(o);
}
int query(int o, int l, int r, int x, int y) {
    int ret = 0;
    if (x<=l&&r<=y) {
        return sumv[o];
    }
    if (x<=M) ret += query(lc, l, M, x, y);
    if (M<y)  ret += query(rc, M+1, r, x, y);
    return ret;
}
void clear() {
    for (int i=0;i<=n*4;i++) {
        sumv[i] = 0;
    }
}
void init() {
    clear();
    for (int i=1;i<=n;i++) scanf("%d", &a[i]), sa[i] = a[i];
    sort(sa+1, sa+1+n), siz = unique(sa+1, sa+1+n) - sa;
    for (int i=1;i<=n;i++) {
        a[i] = lower_bound(sa+1, sa+siz, a[i]) - sa;
    }
}
void solve() {
    LL ans = 0;
    for (int i=1;i<=n;i++) {
        ans += query(1,1,n,a[i],n);
        update(1,1,n,a[i]);
    }
    printf("%lld\n", ans);
}
int main() {
    while (scanf("%d", &n)==1&&n) init(), solve();
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值