P4396 [AHOI2013]宿題(Moチーム+レンジブロック)

トピックリンク:P4396[AHOI2013]割り当て

一般的なアイデア

nnの長さが与えられたnのシーケンス、mmmクエリ、各クエリが与えられl r a bます。

クエリが間隔[l、r] [l、r]にあることを示します[ l r ]、範囲[a、b] [a、b][ a b ]、いくつの値があり、いくつの異なる値があります。

問題解決のアイデア

Moチーム+レンジブロック

MoチームによってO(n)O(\ sqrt {n})を実行します_n [l、r] [l、r]を維持し[ l r ]のすべての数値情報は、クエリを実行するときに、 O(n)O(\ sqrt {n})をブロックすることによって実行され_n クエリ。

➡️同様のトピックの推奨事項⬅️

ACコード

#include <bits/stdc++.h>
#define rep(i, n) for (int i = 1; i <= (n); ++i)
using namespace std;
typedef long long ll;
const int N = 1E5 + 10, B = 320;
int w[N];
struct mo {
    
    
	int l, r, a, b, id;
	bool operator< (const mo& t) const {
    
    
		if (l / B != t.l / B) return l < t.l;
		return l / B & 1 ? r < t.r : r > t.r;
	}
}; vector<mo> area;


int num[N], bcou[B], bhave[B];
pair<int, int> res[N];
void add(int c) {
    
    
	num[c]++, bcou[c / B]++;
	if (num[c] == 1) bhave[c / B]++;
}
void sub(int c) {
    
    
	num[c]--, bcou[c / B]--;
	if (!num[c]) bhave[c / B]--;
}
pair<int, int> ask(int a, int b) {
    
    
	int cou1 = 0, cou2 = 0;
	if (a / B == b / B) {
    
     // 同块
		while (a <= b) cou1 += num[a], cou2 += num[a++] != 0;
		return {
    
     cou1, cou2 };
	}

	int ba = a / B, bb = b / B;
	while (a / B == ba) cou1 += num[a], cou2 += num[a++] != 0;
	while (b / B == bb) cou1 += num[b], cou2 += num[b--] != 0;

	for (int i = a / B; i <= b / B; ++i) {
    
    
		cou1 += bcou[i], cou2 += bhave[i];
	}

	return {
    
     cou1, cou2 };
}
int main()
{
    
    
	int n, m; cin >> n >> m;
	rep(i, n) scanf("%d", &w[i]);
	rep(i, m) {
    
    
		int l, r, a, b;
		scanf("%d %d %d %d", &l, &r, &a, &b);
		area.push_back({
    
     l, r, a, b, i });
	}
	sort(area.begin(), area.end());

	int L = 1, R = 0;
	for (auto& [l, r, a, b, id] : area) {
    
    
		while (l < L) add(w[--L]);
		while (r > R) add(w[++R]);
		while (L < l) sub(w[L++]);
		while (R > r) sub(w[R--]);

		res[id] = ask(a, b);
	}

	rep(i, m) printf("%d %d\n", res[i].first, res[i].second);

	return 0;
}

終わり

おすすめ

転載: blog.csdn.net/weixin_45799835/article/details/121272549
おすすめ