[板子]线段树求逆序对

RT,板子题不会像题解一样细讲,只是记录一下,以防考试板子打错

这棵线段树是一棵权值线段树!

#include <bits/stdc++.h>
using namespace std;

const int N = 500000;
typedef long long LL;

int n;
int m;
LL ans;
int a[N + 30];
int b[N + 30];

struct ST
{
    int l, r;
    LL sum;
}t[N * 8 + 30];

int read()
{
    int s = 0, f = 1;
    char ch = getchar();
    while (ch < '0' || ch > '9')
    {
        if (ch == '-') f = -1;
        ch = getchar();
    }
    while (ch >= '0' && ch <= '9')
    {
        s = s * 10 + ch - '0';
        ch = getchar();
    }
    return s * f;
}

inline void built(int p, int l, int r)
{
    t[p].l = l;
    t[p].r = r;
    if (l == r)
        return ;
    int mid = (l + r)>>1;
    built(p<<1, l, mid);
    built(p<<1|1, mid + 1, r);   
}
inline void change(int p, int s)
{
    if (t[p].l == s && t[p].r == s)
    {
        ++t[p].sum;
        return ;
    }
    int mid =(t[p].l + t[p].r)>>1;
    if (s <= mid)
        change(p<<1, s);
    else
        change(p<<1|1, s);
    t[p].sum = t[p<<1].sum + t[p<<1|1].sum;
}
LL ask(int p, int l, int r)
{
    if (t[p].l >= l && t[p].r <= r)
        return t[p].sum;
    LL tot = 0;
    int mid = (t[p].l + t[p].r) >> 1;
    if (l <= mid)
        tot += ask(p<<1, l, r);
    if (mid < r)
        tot += ask(p<<1|1, l, r);
    return tot;
}

int main()
{
    n = read();
    for (int i = 1; i <= n; ++i)
    {
        a[i] = read();
        b[i] = a[i];
    }
    sort(b + 1, b + n + 1);
    m = unique(b + 1, b + n + 1) - b;
    for (int i = 1; i <= n; ++i)
        a[i] = lower_bound(b + 1, b + n + 1, a[i]) - b;
    built(1, 1, n);
    for (int i = 1; i <= n; ++i)
    {
        change(1, a[i]);
        ans += i - ask(1, 1, a[i]);
    }
    printf ("%lld\n", ans);
    return 0;
}
posted @ 2020-08-24 13:56  marTixx  阅读(81)  评论(1编辑  收藏  举报