LuoguP3674 小清新人渣的本願
阿新 • • 發佈:2018-12-31
題目地址
題解
這種lxl的題還是沒修改操作的題基本就是莫隊
分開考慮每個詢問
1.減法
\(a-b=x⇒a=b+x\)
用一個\(bitset\),第\(i\)位表示有沒有\(i\)這個數
那麼查詢其實就等價於查詢bit&(bit>>x)之後裡面有沒有1
\(a+b=x\)
2.加法
\(a+b=x\)
設\(p=n-b\)
\(a-p=a-n+b=x-n\)
維護一下另外一個\(bitset\),裡面存的是\(n-i\)有沒有出現過
查詢直接查bit1&(bit2>>(n-x))裡面有沒有1就好
3.乘法
乘法不好維護
但是直接列舉因數也是可以的,在第一個bitset裡面看成對的因數有沒有出現過就好
#include <cstdio> #include <algorithm> #include <cstring> #include <cmath> #include <bitset> using namespace std; inline int read() { int x = 0, f = 1; char c = getchar(); while(c < '0' || c > '9') {if(c == '-') f = -1; c = getchar();} while(c >= '0' && c <= '9') {x = x * 10 + c - '0'; c = getchar();} return x * f; } #define N 100010 bitset<N>s1; bitset<N>s2; int cnt[N]; int n, m, a[N]; int ans[N], block; struct ques { int opt, l, r, x, id; } q[N]; bool cmp(ques a, ques b) { if(a.l / block == b.l / block) return a.r < b.r; else return a.l < b.l; } void add(int x) { x = a[x]; cnt[x]++; if(cnt[x] == 1) s1[x] = s2[n - x] = true; } void dele(int x) { x = a[x]; cnt[x]--; if(!cnt[x]) s1[x] = s2[n - x] = false; } int main() { n = read(); m = read(); for(int i = 1; i <= n; i ++) a[i] = read(); block = n / sqrt(m); for(int i = 1; i <= m; i ++) { q[i] = (ques) {read(), read(), read(), read(), i}; } sort(q + 1, q + m + 1, cmp); int l = 1, r = 0; for(int i = 1; i <= m; i ++) { int ql = q[i].l, qr = q[i].r, opt = q[i].opt, x = q[i].x; while(l < ql) dele(l++); while(l > ql) add(--l); while(r < qr) add(++r); while(r > qr) dele(r--); if(opt == 1) { ans[q[i].id] = (s1 & (s1 >> x)).any(); } if(opt == 2) { ans[q[i].id] = (s1 & (s2 >> (n - x))).any(); } if(opt == 3) { for(int k = 1; k * k <= x; k ++) { if(x % k == 0) { if(s1[k] && s1[x / k]) { ans[q[i].id] = 1; break; } } } } } for(int i = 1; i <= m; i ++) { puts(ans[i] ? "hana" : "bi"); } return 0; }