离散,然后树状数组+莫队。
最初用的是直接粘过来的1488的sbt,然后极限随机数据要跑14s。好郁闷。
然后改用数状数组就变1s了。是我再次把sbt写丑了还是它常数够厉害TT
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
struct query {
int i, l, r, pl, pr;
};
typedef unsigned int uint;
const int maxn = 50009;
#define update(_p_) (sz[_p_]=sz[ls[_p_]]+sz[rs[_p_]]+1)
inline bool cmpQry(const query& a, const query& b) {
return a. pl < b. pl || (a. pl == b. pl && a. pr > b. pr);
}
inline bool cmpP(int* a, int* b) {
return *a < *b;
}
int n, m, bsz, a[maxn], *r[maxn], maxa, t[maxn];
uint ans[maxn];;
query q[maxn];
void btChg(int* t, int p, int v) {
for (; p <= maxa; p += (p & -p))
t[p] += v;
}
int btQry(int* t, int p) {
int s = 0;
for (; p; p -= (p & -p))
s += t[p];
return s;
}
int main() {
#ifndef ONLINE_JUDGE
freopen("in.txt", "r", stdin);
#endif
scanf("%d", &n);
for (int i = 1; i <= n; ++ i)
scanf("%d", a + i), r[i - 1] = a + i;
sort(r, r + n, cmpP);
maxa = 0;
for (int i = 0, l = *r[0] - 1; i < n; ++ i)
if (*r[i] == l)
*r[i] = maxa;
else
l = *r[i], *r[i] = ++ maxa;
for (bsz = 1; bsz * bsz < n; ++ bsz);
scanf("%d", &m);
for (int i = 0; i < m; ++ i) {
scanf("%d%d", &q[i]. l, &q[i]. r);
q[i]. i = i;
q[i]. pl = q[i]. l / bsz;
q[i]. pr = q[i]. r / bsz;
}
sort(q, q + m, cmpQry);
int l = 1, r = 1;
memset(t, 0, sizeof(t));
btChg(t, a[1], 1);
uint tot = 0;
for (int i = 0; i < m; ++ i) {
while (r < q[i]. r) {
++ r;
tot += r - l - btQry(t, a[r]);
btChg(t, a[r], 1);
}
while (l > q[i]. l) {
-- l;
tot += btQry(t, a[l] - 1);
btChg(t, a[l], 1);
}
while (r > q[i]. r) {
btChg(t, a[r], -1);
tot -= r - l - btQry(t, a[r]);
-- r;
}
while (l < q[i]. l) {
btChg(t, a[l], -1);
tot -= btQry(t, a[l] - 1);
++ l;
}
ans[q[i]. i] = tot;
}
for (int i = 0; i < m; ++ i)
printf("%u\n", ans[i]);
}