luogu P3674 小清新人渣的本愿

https://www.luogu.com.cn/problem/P3674

首先肯定是莫队
然后考虑如何判断,发现差可以直接用bitset
加法就整个数反过来(相当于取补集),然后再bitset
乘积随便搞
啊讲不清
看这篇吧
https://www.luogu.com.cn/blog/juruoforever/solution-p3674
code:

#include<bits/stdc++.h>
#define N 100005
using namespace std;
struct Q {
	int opt, x, l, r, id;
} q[N];
int bel[N], a[N], n, m, k, cnt[N * 3], ans[N];
bitset<N> s1, s2;
int cmp(Q x, Q y) {
	if(bel[x.l] != bel[y.l]) return x.l < y.l;
	if(bel[x.l] & 1) return x.r < y.r;
	return x.r > y.r;
}
void add(int id) {
	s1[a[id]] = s2[100000 - a[id]] = ++ cnt[a[id]] != 0;
}
void del(int id) {
	s1[a[id]] = s2[100000 - a[id]] = -- cnt[a[id]] != 0;
}
int main() {
	scanf("%d%d", &n, &m);
	for(int i = 1; i <= n; i ++) scanf("%d", &a[i]);
	for(int i = 1; i <= m; i ++) scanf("%d%d%d%d", &q[i].opt, &q[i].l, &q[i].r, &q[i].x), q[i].id = i;
	int blo = max(1.0, n / sqrt(m));
	for(int i = 1; i <= n; i ++) bel[i] = (i - 1) / blo + 1;
	sort(q + 1, q + 1 + m, cmp);
	int l = 1, r = 0;
	for(int i = 1; i <= m; i ++) {
		while(r < q[i].r) add(++ r);
		while(l > q[i].l) add(-- l);
		while(r > q[i].r) del(r --);
		while(l < q[i].l) del(l ++);
		if(q[i].opt == 1) ans[q[i].id] = (s1&(s1 << q[i].x)).any();
		else if(q[i].opt == 2) ans[q[i].id] = (s1&(s2 >> (100000 - q[i].x))).any();
		else {
			for(int d = 1; d * d <= q[i].x; d ++) if(q[i].x % d == 0) {
				if(s1[d] && s1[q[i].x / d]) {
					ans[q[i].id] = 1;
					break;
				}
			}
		}
	}
	for(int i = 1; i <= m; i ++) 
		if(ans[i]) printf("hana\n");
		else printf("bi\n");
	return 0;
}

正难则反
这不是基本套路嘛?
做什么都应该这么想啊

posted @ 2021-04-07 21:01  lahlah  阅读(63)  评论(0编辑  收藏  举报