hdu5792--World is Exploding

题意:给一个数列,求四个各不相同的数,一个逆序对,一个正序对,求多少组这样的四个数。

题解:辣鸡如我,还是上官方题解了。

rg(i)就是i右边比i大的数的个数,rs(i)就是i右边比i小的数的个数。

lg(i)就是i左边比i大的数的个数,ls(i)就是i左边比i小的数的个数。

allg就是所有逆序对的个数,∑rs(i)或者∑lg(i)都可以。

然后答案就是对于每一个数,当它为正序对中较小的那个数时的答案相加。

这样算会有重复,就是那个正序对中较大的数也被算入了逆序对中,所以再减去每个数字作为正序对较大的数时的它所可能的逆序对数量。

注意用会超int 用long long

// 2016多校5-1012/hdu5792
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <iostream>
#include <queue>
#include <vector>
#include <cmath>
using namespace std;
#define PF(x) cout << "debug:" << x << " ";
 
const int N = 50005;
typedef long long ll;
int a[N], b[N];
int lg[N], ls[N], rg[N], rs[N];

int bit[N];

int lowbit(int x) { return x&-x; }

void add(int p, int v, int n)
{
    while (p <= n) {
        bit[p] += v;
        p += lowbit(p);
    }
}

ll sum(int p)
{
    ll ans = 0;
    while (p > 0) {
        ans += bit[p];
        p -= lowbit(p);
    }
    return ans;
}



int main(int argc, char const *argv[])
{
    freopen("in", "r", stdin);
    int n;
    while (~scanf("%d", &n)) {
        for (int i = 1; i <= n; ++i) {
            scanf("%d", a+i);
            b[i] = a[i];
        }
        //离散话
        sort(a+1, a+n+1);
        int tot = unique(a+1, a+n+1) - a;
        for (int i = 1; i <= n; ++i) {
            b[i] = lower_bound(a, a+tot, b[i]) - a;
        }
        //for (int i = 1; i <= n; ++i) printf("%d
", b[i]);
        //求lg ls
        memset(bit, 0, sizeof bit);
        for (int i = 1; i <= n; ++i) {
            ls[i] = sum(b[i]-1);
            lg[i] = i - 1 - sum(b[i]);
            add(b[i], 1, n);
        }
        //求rg rs
        memset(bit, 0, sizeof bit);
        for (int i = n; i > 0; --i) {
            rs[i] = sum(b[i]-1);
            rg[i] = n - i - sum(b[i]);
            add(b[i], 1, n);
        }
        // cout << "ls "; for (int i = 1; i <= n; ++i) printf("%d ", ls[i]); printf("
");
        // cout << "lg "; for (int i = 1; i <= n; ++i) printf("%d ", lg[i]); printf("
");
        // cout << "rs "; for (int i = 1; i <= n; ++i) printf("%d ", rs[i]); printf("
");
        // cout << "rg "; for (int i = 1; i <= n; ++i) printf("%d ", rg[i]); printf("
");
        //求allg
        ll allg = 0;
        for (int i = 1; i <= n; ++i) allg += lg[i];
        //PF(allg);
        ll ans = 0;
        for (int i = 1; i <= n; ++i) {
            ans += (ll)rg[i] * (allg - lg[i] - rs[i]);
        }
        for (int i = 1; i <= n; ++i) {
            ans -= (ll)ls[i] * (lg[i] + rs[i]);
        }
        cout << ans << endl;
    }
    return 0;
}
原文地址:https://www.cnblogs.com/wenruo/p/5731415.html