bzoj 3236 [Ahoi2013]作业 莫队+树状数组

题面

题目传送门

解法

离线询问,然后莫队

建2棵权值树状数组,一棵为区间有多少个数,另一棵为区间有多少个不同的数

在扩展区间的时候用树状数组修改即可

代码

#include <bits/stdc++.h>
#define N 3000010
using namespace std;
template <typename node> void chkmax(node &x, node y) {x = max(x, y);}
template <typename node> void chkmin(node &x, node y) {x = min(x, y);}
template <typename node> void read(node &x) {
	x = 0; int f = 1; char c = getchar();
	while (!isdigit(c)) {if (c == '-') f = -1; c = getchar();}
	while (isdigit(c)) x = x * 10 + c - '0', c = getchar(); x *= f;
}
int n, m, len, a[N], c[N], col[N], cnt[N], ans[N][2];
struct Node {
	int l, r, x, y, id;
} b[N];
struct BIT {
	int f[N];
	int lowbit(int x) {return x & -x;}
	void modify(int x, int v) {
		for (int i = x; i <= len; i += lowbit(i))
			f[i] += v;
	}
	int query(int x) {
		int ret = 0;
		for (int i = x; i; i -= lowbit(i))
			ret += f[i];
		return ret;
	}
} T1, T2;
bool cmp(Node a, Node b) {
	return col[a.l] == col[b.l] ? a.r < b.r : a.l < b.l;
}
void update(int x, int v) {
	cnt[a[x]] += v; T1.modify(a[x], v);
	if (v == 1)
		if (cnt[a[x]] == 1) T2.modify(a[x], 1);
	if (v == -1)
		if (!cnt[a[x]]) T2.modify(a[x], -1);
}
main() {
	read(n), read(m); len = 0;
	for (int i = 1; i <= n; i++)
		read(a[i]), c[++len] = a[i];
	int siz = (int)sqrt(n);
	for (int i = 1; i <= n; i++) col[i] = (i + siz - 1)  / siz;
	for (int i = 1; i <= m; i++) {
		read(b[i].l), read(b[i].r), read(b[i].x), read(b[i].y), b[i].id = i;
		c[++len] = b[i].x, c[++len] = b[i].y;
	}
	sort(c + 1, c + len + 1);
	len = unique(c + 1, c + len + 1) - c - 1;
	map <int, int> h;
	for (int i = 1; i <= len; i++) h[c[i]] = i;
	for (int i = 1; i <= n; i++) a[i] = h[a[i]];
	for (int i = 1; i <= m; i++)
		b[i].x = h[b[i].x], b[i].y = h[b[i].y];
	sort(b + 1, b + m + 1, cmp);
	for (int i = 1, l = 1, r = 0; i <= m; i++) {
		while (r < b[i].r) update(++r, 1);
		while (r > b[i].r) update(r--, -1);
		while (l < b[i].l) update(l++, -1);
		while (l > b[i].l) update(--l, 1);
		ans[b[i].id][0] = T1.query(b[i].y) - T1.query(b[i].x - 1);
		ans[b[i].id][1] = T2.query(b[i].y) - T2.query(b[i].x - 1);
	}
	for (int i = 1; i <= m; i++)
		cout << ans[i][0] << ' ' << ans[i][1] << "\n";
	return 0;
}

posted @ 2018-08-14 22:12  谜のNOIP  阅读(133)  评论(0编辑  收藏  举报