题目

bzoj3289

思路

区间求逆序对
离散化+莫队+树状数组修改

代码

/**************************************************************
    Problem: 3289
    User: 3010651817
    Language: C++
    Result: Accepted
    Time:5716 ms
    Memory:3064 kb
****************************************************************/
 
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <cmath>
#define FOR(i,a,b) for(int i=a;i<=b;++i)
using namespace std;
const int maxn = 5e4 + 7;
const int N = 5e4;
int read() {
    int x = 0, f = 1; char s = getchar();
    for (; s > '9' || s < '0'; s = getchar()) if (s == '-') f = -1;
    for (; s >= '0' && s <= '9'; s = getchar()) x = x * 10 + s - '0';
    return x * f;
}
struct node {
    int l, r, id, ans;
} Q[maxn];
int n, m, a[maxn], b[maxn], sum[maxn << 1], belong[maxn], ans;
bool cmp1(node a, node b) {return belong[a.l] == belong[b.l] ? a.r < b.r : belong[a.l] < belong[b.l];}
bool cmp2(node a, node b) {return a.id < b.id;}
int lowbit(int x) {return x & -x;}
void update(int x, int ad) {
    for (int i = x; i <= N; i += lowbit(i)) sum[i] += ad;
}
int query(int x) {
    int ans = 0;
    for (int i = x; i >= 1; i -= lowbit(i)) ans += sum[i];
    return ans;
}
int main() {
    n = read();
    int zz = sqrt(n);
    FOR(i, 1, n) b[i] = a[i] = read();
    sort(b + 1, b + 1 + n);
    FOR(i, 1, n) a[i] = lower_bound(b + 1, b + 1 + n, a[i]) - b;
    FOR(i, 1, n) belong[i] = (i - 1) / zz + 1;
    m = read();
    FOR(i, 1, m) Q[i].l = read(), Q[i].r = read(), Q[i].id = i;
    sort(Q + 1, Q + 1 + m, cmp1);
    int l = 1, r = 0;
    FOR(i, 1, m) {
        while (l < Q[i].l) {update(a[l], -1);ans -= query(a[l] - 1);++l;}
        while (r > Q[i].r) {update(a[r], -1);ans -= r - l - query(a[r]);--r;}
        while (l > Q[i].l) {--l;update(a[l], 1);ans += query(a[l] - 1);}
        while (r < Q[i].r) {++r;update(a[r], 1);ans += r - l + 1 - query(a[r]);}
        Q[i].ans = ans;
    }
    sort(Q + 1, Q + 1 + m, cmp2);
    FOR(i, 1, m) printf("%d\n", Q[i].ans);
    return 0;
}