[洛谷P3674]小清新人渣的本愿
题目传送门
这道题是一道莫队题。对于每一种问法,就是查询对应的数是否在当前的区间内。
设$b[i]$表示莫队当前区间中有没有$i$这个数。
对于第一问“是否可以选出两个数它们的差为x”,也就是判断当$i-j=x$时是否存在$b[i],b[j]=1$。变形一下发现$i=j+x$,就成了$b[j],b[j+x]=1$。
我们用一个$\text{bitset}$操作,判断这一问就变成了判断$(b\ \text{&&}\ (b<<x))$是否为真。
对于第二问就是当$i+j=x$时,是否存在$b[i],b[j]=1$。变形下发现
$$i=x-j$$
$$i+N=x+N-j$$
$$i-(x-N)=(N-j)$$
再开个$b'=\text{bitset}$维护$N-j$,当$j$出现后,$N-j$为$1$。答案即为$((b<<(N-x))\ \text{&&}\ b')$。
对于第三问发现枚举因数直接判断复杂度不大,暴力解决。
一开始计算复杂度发现是$O(m\sqrt{n}+mn)$,$mn$复杂度是由$\text{bitset}$的与运算贡献的,会炸的。
但后来了解到$\text{bitset}$的复杂度要除掉一个$\omega$,$\omega$为计算机位数,一般为$32/64$。
所以就能卡过了。
下面的代码的写法可能与上面有细微差别,但与上面是等效的。
1 #include <bits/stdc++.h> 2 3 using namespace std; 4 5 #define re register 6 #define rep(i, a, b) for (re int i = a; i <= b; ++i) 7 #define repd(i, a, b) for (re int i = a; i >= b; --i) 8 #define maxx(a, b) a = max(a, b); 9 #define minn(a, b) a = min(a, b); 10 #define LL long long 11 #define INF (1 << 30) 12 13 inline int read() { 14 int w = 0, f = 1; char c = getchar(); 15 while (!isdigit(c)) f = c == '-' ? -1 : f, c = getchar(); 16 while (isdigit(c)) w = (w << 3) + (w << 1) + (c ^ '0'), c = getchar(); 17 return w * f; 18 } 19 20 const int maxn = 1e5 + 5; 21 22 bitset<maxn> S1, S2; 23 24 struct Query { 25 int l, r, id, pos, opt, x; 26 } q[maxn]; 27 bool cmp(Query a, Query b) { return a.pos < b.pos || a.pos == b.pos && a.r < b.r; } 28 29 int n, m, a[maxn], ans, b[maxn], size, cnt[maxn]; 30 31 void del(int x) { cnt[x]--; if (!cnt[x]) S1[x] = S2[n-x] = 0; } 32 void ins(int x) { if (!cnt[x]) S1[x] = S2[n-x] = 1; cnt[x]++; } 33 34 int main() { 35 n = read(), m = read(); 36 size = sqrt(n); 37 rep(i, 1, n) a[i] = read(); 38 rep(i, 1, m) q[i].opt = read(), q[i].l = read(), q[i].r = read(), q[i].x = read(), q[i].id = i, q[i].pos = (q[i].l + size - 1) / size; 39 sort(q+1, q+m+1, cmp); 40 int pl = 1, pr = 0; 41 rep(i, 1, m) { 42 while (pl < q[i].l) del(a[pl]), pl++; 43 while (pl > q[i].l) pl--, ins(a[pl]); 44 while (pr < q[i].r) pr++, ins(a[pr]); 45 while (pr > q[i].r) del(a[pr]), pr--; 46 if (q[i].opt == 1) { 47 b[q[i].id] = ((S1 << q[i].x) & S1).any() ? 1 : 0; 48 } 49 else if (q[i].opt == 2) { 50 b[q[i].id] = ((S2 >> (n-q[i].x)) & S1).any() ? 1 : 0; 51 } 52 else if (q[i].opt == 3) { 53 b[q[i].id] = 0; 54 rep(x, 1, sqrt(q[i].x)) 55 if (!(q[i].x % x) && S1[x] && S1[q[i].x/x]) { b[q[i].id] = 1; break; } 56 } 57 } 58 rep(i, 1, m) printf("%s\n", b[i] ? "hana" : "bi"); 59 return 0; 60 }