BZOJ 3744 Gty的妹子序列 分块+树状数组+主席树

版权声明:本人版权意识薄弱,请随意转载 https://blog.csdn.net/Ike940067893/article/details/88775402

这个做法是 O ( n n l o g n ) O(n\sqrt nlogn) 的主席树…
(其实还有不用主席树,只用分块+树状数组的 O ( n n l o g n ) O(n\sqrt nlogn) ,因为常数小,快了一倍 戳这里)

CODE

貌似把块大小开成根号要12500ms,但是开成100只要9500ms…

#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 ans = 0, x, y;
	read(m);
	while(m--) {
		read(x), read(y), x ^= ans, y ^= ans;
		printf("%d\n", ans=solve(x, y));
	}
}

猜你喜欢

转载自blog.csdn.net/Ike940067893/article/details/88775402