BZOJ 3289: Mato的文件管理 (区间查询逆序对)

这道题就是不要求强制在线的 BZOJ 3744 Gty的妹子序列

所以说离线做法有莫队,在线做法见上面连接.

这里贴出常数巨大O(nnlogn)O(nsqrt nlogn)分块+树状数组+主席树做法.

CODE

#include <cmath>
#include <cstdio>
#include <cstring>
#include <algorithm>
using namespace std;
template<typename T>inline void read(T &num) {
	char ch; int flg = 1;
	while((ch=getchar())<'0'||ch>'9')if(ch=='-')flg=-flg;
	for(num=0;ch>='0'&&ch<='9';num=num*10+ch-'0',ch=getchar());
	num*=flg;
}
const int MAXN = 50005;
int n, m, N, B, f[225][MAXN], a[MAXN], b[MAXN], bel[MAXN];

int ch[MAXN*20][2], sz[MAXN*20], rt[MAXN], tot;
void insert(int &i, int p, int l, int r, int x) {
	sz[i=++tot] = sz[p] + 1;
	if(l == r) return;
	int mid = (l + r) >> 1;
	if(x <= mid) ch[i][1] = ch[p][1], insert(ch[i][0], ch[p][0], l, mid, x);
	else ch[i][0] = ch[p][0], insert(ch[i][1], ch[p][1], mid+1, r, x);
}

int query(int x, int y, int l, int r, int L, int R) {
	if(sz[x] == sz[y]) return 0;
	if(L <= l && r <= R) return sz[y]-sz[x];
	int mid = (l + r) >> 1;
	if(R <= mid) return query(ch[x][0], ch[y][0], l, mid, L, R);
	else if(L > mid) return query(ch[x][1], ch[y][1], mid+1, r, L, R);
	return query(ch[x][0], ch[y][0], l, mid, L, R) + query(ch[x][1], ch[y][1], mid+1, r, L, R);
}

int T[MAXN];

inline void upd(int x, int val) {
	while(x) T[x] += val, x -= x&-x;
}
inline int qsum(int x) { int res = 0;
	while(x <= N) res += T[x], x += x&-x;
	return res;
}
inline int solve(int L, int R) {
	if(L > R) swap(L, R);
	int res = 0;
	if(bel[L] == bel[R]) {
		for(int i = L; i <= R; ++i)
			res += qsum(a[i]+1), upd(a[i], 1);
		for(int i = L; i <= R; ++i) upd(a[i], -1);
		return res;
	}
	res = f[bel[L]+1][R];
	for(int i = L; i <= bel[L]*B && i < R; ++i)
		res += query(rt[i], rt[R], 1, N, 1, a[i]-1);
	return res;
}

int main () {
	read(n); B = sqrt(n);
	for(int i = 1; i <= n; ++i) read(a[i]), b[++N] = a[i];
	sort(b + 1, b + N + 1);
	N = unique(b + 1, b + N + 1) - b - 1;
	for(int i = 1; i <= n; ++i) a[i] = lower_bound(b + 1, b + N + 1, a[i]) - b;
	for(int i = 1; i <= n; ++i) {
		bel[i] = (i-1)/B + 1;
		insert(rt[i], rt[i-1], 1, N, a[i]);
	}
	for(int i = 1; i <= bel[n]; ++i) {
		for(int j = (i-1)*B+1; j <= n; ++j)
			f[i][j] = f[i][j-1] + qsum(a[j]+1), upd(a[j], 1);
		memset(T, 0, (N+1)<<2);
	}
	int x, y;
	read(m);
	while(m--) {
		read(x), read(y);
		printf("%d
", solve(x, y));
	}
}
原文地址:https://www.cnblogs.com/Orz-IE/p/12039378.html