【题目链接】
https://www.lydsy.com/JudgeOnline/problem.php?id=4810
【题解】
首先可以离线下来使用莫队,这样就知道了每个询问区间中每个数是否出现,将其压为一个bitset,记为
f
f
。
考虑如何询问:
对于操作1:可行的条件是^
f<<x
f
<<
x
不全为
0
0
。
对于操作2:记表示
f
f
翻转后的结果(第i位于第(最高位-i)位替换),那么可行的条件是^
g<<(最高位−x)
g
<<
(
最
高
位
−
x
)
不全为0。
对于操作3:直接枚举
x
x
的因数。
时间复杂度
【代码】
/* - - - - - - - - - - - - - - -
User : VanishD
problem : [bzoj4810]
Points : bitset
- - - - - - - - - - - - - - - */
# include <bits/stdc++.h>
# define ll long long
# define inf 0x3f3f3f3f
# define N 100010
using namespace std;
int read(){
int tmp = 0, fh = 1; char ch = getchar();
while (ch < '0' || ch > '9'){ if (ch == '-') fh = -1; ch = getchar(); }
while (ch >= '0' && ch <= '9'){ tmp = tmp * 10 + ch - '0'; ch = getchar(); }
return tmp * fh;
}
struct Node{
int opt, l, r, x, id;
}q[N];
bool ans[N];
int use[N];
int n, m, size, num[N];
bitset <N> hav0, hav1;
bool cmp(Node x, Node y){
return x.l / size < y.l / size || (x.l / size == y.l / size && x.r < y.r);
}
inline void ins(int x){hav0.set(x); hav1.set(N - x);}
inline void del(int x){hav0.reset(x); hav1.reset(N - x);}
int main(){
// freopen("bzoj4810.in", "r", stdin);
// freopen("bzoj4810.out", "w", stdout);
n = read(), m = read();
for (int i = 1; i <= n; i++) num[i] = read();
size = (int)pow(n, 0.5);
for (int i = 1; i <= m; i++){
q[i].opt = read(), q[i].l = read(), q[i].r = read(), q[i].x = read();
q[i].id = i;
}
sort(q + 1, q + m + 1, cmp);
int nowl = 1, nowr = 0;
for (int i = 1; i <= m; i++){
for (int j = nowr + 1; j <= q[i].r; j++){
use[num[j]]++;
if (use[num[j]] == 1) ins(num[j]);
}
for (int j = nowl - 1; j >= q[i].l; j--){
use[num[j]]++;
if (use[num[j]] == 1) ins(num[j]);
}
for (int j = nowl; j < q[i].l; j++){
use[num[j]]--;
if (use[num[j]] == 0) del(num[j]);
}
for (int j = nowr; j > q[i].r; j--){
use[num[j]]--;
if (use[num[j]] == 0) del(num[j]);
}
nowl = q[i].l; nowr = q[i].r;
if (q[i].opt == 1)
if ((hav0 & (hav0 << q[i].x)).any() != 0)
ans[q[i].id] = true;
if (q[i].opt == 2)
if ((hav0 & (hav1 >> (N - q[i].x))).any() != 0)
ans[q[i].id] = true;
if (q[i].opt == 3){
bool flag = false;
for (int j = 1; j * j <= q[i].x; j++){
if (q[i].x % j != 0) continue;
if (use[j] != 0 && use[q[i].x / j] != 0){
flag = true;
break;
}
}
if (flag == true) ans[q[i].id] = true;
}
}
for (int i = 1; i <= m; i++)
puts((ans[i] == true) ? "yuno" : "yumi");
return 0;
}