社区讨论

MnZn刚学莫队在线求助

P4396[AHOI2013] 作业参与者 3已保存回复 7

讨论操作

快速查看讨论及其快照的属性,并进行相关操作。

当前回复
7 条
当前快照
1 份
快照标识符
@mhjv0k2s
此快照首次捕获于
2025/11/04 08:57
4 个月前
此快照最后确认于
2025/11/04 08:57
4 个月前
查看原帖
TLE On #13 加上奇偶性优化反而多T一个。。
CPP
#include<bits/stdc++.h>

namespace IO {
	inline int read() {
		int ret = 0, f = 1;char ch = getchar();
		while (ch < '0' || ch > '9') {
			if (ch == '-')  f = -f;
			ch = getchar();
		}
		while (ch >= '0' && ch <= '9') {
			ret = (ret << 1) + (ret << 3) + (ch ^ 48);
			ch = getchar();
		}
		return ret * f;
	}
	void write(int x) {
		if (x < 0) putchar('-'), x = -x;
		if (x > 9) write(x / 10);
		putchar(x % 10 + '0');
	}
}

using namespace IO;
using namespace std;

const int maxn = 1e5 + 5;

int n, m, Max;
int L[maxn], R[maxn], f[maxn];
pair<int, int> Ans[maxn];
struct Node {
	int l, r, a, b, id;
	bool operator == (const Node & x) const {
		return x.l == l && x.r == r && x.a == a && x.b == b;
	}
};
int a[maxn], sum[maxn], s[maxn], num[maxn], len;
Node q[maxn];

bool cmp(Node a, Node b) {
	int fa = (a.l - 1) / len + 1, fb = (b.l - 1) / len + 1;
	return fa == fb ? a.r < b.r : a.l < b.l;
}

void init() {
	int x = sqrt(Max);
	for (int i = 1;i <= x;i++) {
		L[i] = (i - 1) * x + 1;
		R[i] = i * x;
		for (int j = L[i];j <= R[i];j++) f[j] = i;
	}
	if (R[x] != n) {
		L[++x] = R[x - 1] + 1;
		R[x] = n;
		for (int i = L[x];i <= R[x];i++) f[i] = x;
	}
}

void add(int x) {
	if (a[s[x]] == 0) num[f[s[x]]]++;
	a[s[x]]++, sum[f[s[x]]]++;
}

void del(int x) {
	if (a[s[x]] == 1) num[f[s[x]]]--;
	a[s[x]]--, sum[f[s[x]]]--;
}

pair<int, int> query(int l, int r) {
	r = min(r, Max);
	int lk = f[l], rk = f[r];
	pair<int, int> cnt;cnt.first = 0, cnt.second = 0;
	
	if (lk == rk) {
		for (int i = l;i <= r;i++) {
			cnt.second += (a[i] > 0);
			cnt.first += a[i];
		}
		return cnt;
	}
	
	for (int i = l;i <= R[lk];i++) {
		cnt.second += (a[i] > 0);
		cnt.first += a[i];
	}
	for (int i = lk + 1;i < rk;i++) cnt.first += sum[i], cnt.second += num[i];
	for (int i = L[rk];i <= r;i++) {
		cnt.second += (a[i] > 0);
		cnt.first += a[i];
	}
	
	return cnt;
}

int main() {
	n = read(), m = read();len = sqrt(m);
	for (int i = 1;i <= n;i++) s[i] = read(), Max = max(Max, s[i]);
	for (int i = 1;i <= m;i++) q[i].l = read(), q[i].r = read(), q[i].a = read(), q[i].b = read(), q[i].id = i;

	sort(q + 1, q + 1 + m, cmp);
	
	for (int i = 1, l = 1, r = 0;i <= m;i++) {
		if (q[i] == q[i - 1]) {
			Ans[q[i].id] = Ans[q[i - 1].id];
			continue;
		}
		while (l > q[i].l) add(--l);
		while (r < q[i].r) add(++r);
		while (l < q[i].l) del(l++);
		while (r > q[i].r) del(r--);
		Ans[q[i].id] = query(q[i].a, q[i].b);
	}
	
	for (int i = 1;i <= m;i++) write(Ans[i].first), putchar(' '), write(Ans[i].second), putchar(10);
	
	return 0;
}

回复

7 条回复,欢迎继续交流。

正在加载回复...