bzoj3289 Mato的文件管理
题目
思路
区间求逆序对
离散化+莫队+树状数组修改
代码
/**************************************************************
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;
}