题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4810
Description
由乃在自己的农田边散步,她突然发现田里的一排玉米非常的不美。这排玉米一共有N株,它们的高度参差不齐。
由乃认为玉米田不美,所以她决定出个数据结构题
这个题是这样的:
给你一个序列a,长度为n,有m次操作,每次询问一个区间是否可以选出两个数它们的差为x,或者询问一个区间是
否可以选出两个数它们的和为x,或者询问一个区间是否可以选出两个数它们的乘积为x ,这三个操作分别为操作1
,2,3选出的这两个数可以是同一个位置的数
Input
第一行两个数n,m
后面一行n个数表示ai
后面m行每行四个数opt l r x
opt表示这个是第几种操作,l,r表示操作的区间,x表示这次操作的x
定义c为每次的x和ai中的最大值,ai >= 0,每次的x>=2n,m,c <= 100000
Output
对于每个询问,如果可以,输出yuno,否则输出yumi
Sample Input
5 5
1 1 2 3 4
2 1 1 2
1 1 2 2
3 1 1 1
3 5 5 16
1 2 3 4
Sample Output
yuno
yumi
yuno
yuno
yumi
解法:qzh打野教我的,考虑一下要对区间信息查询,我们询问离线,跑个莫队,然后用bitset记录下哪些数出现了。然后区间a - b = x -> a = b + x , 同理 a + b = x -> a = x - b -> a = - (b - x),所以对于差为x我们直接把第一个bitset右移然后和自己取交,同理对于和为x的情况,我们对之前的那个bitset取反,进行类似的操作就可以了,然后对于乘法的话 a*b = x我们直接枚举质因子暴力判断即可。
复杂度 : O(n*n/32)
//BZOJ 4810
#include <bits/stdc++.h>
using namespace std;
//a - b = x -> a = b + x
//a + b = x -> a = -b + x -> a = - (b - x)
//a * b = x -> a = x / b
//O(n*n/32)
const int maxn = 100010;
const int offset = 100000;
bitset <maxn> pos;
bitset <maxn> neg;
int n, m, belong[maxn], block, a[maxn], ans[maxn], cnt[maxn];
struct node{
int l, r, x, id, op;
node(){}
node(int l, int r, int x, int id, int op):l(l),r(r),x(x),id(id),op(op){}
bool operator < (const node &rhs) const{
if(belong[l] != belong[rhs.l]){
return belong[l] < belong[rhs.l];
}
else{
return r < rhs.r;
}
}
}q[maxn];
void input()
{
scanf("%d%d", &n, &m);
block = ceil(sqrt(n));
for(int i = 1; i <= n; i++){
scanf("%d", &a[i]);
}
for(int i = 1; i <= n; i++){
belong[i] = (i-1)/block+1;
}
for(int i = 1; i <= m; i++){
scanf("%d%d%d%d", &q[i].op, &q[i].l, &q[i].r, &q[i].x);
q[i].id = i;
}
sort(q + 1, q + m + 1);
}
void work()
{
int L = 1, R = 0;
for(int i = 1; i <= m; i++)
{
int id = q[i].id;
while(R < q[i].r){
R++;
cnt[a[R]]++;
pos[a[R]] = 1;
neg[offset - a[R]] = 1;
}
while(L > q[i].l){
L--;
cnt[a[L]]++;
pos[a[L]] = 1;
neg[offset - a[L]] = 1;
}
while(R > q[i].r){
cnt[a[R]]--;
if(cnt[a[R]] == 0) pos[a[R]] = 0;
if(cnt[a[R]] == 0) neg[offset - a[R]] = 0;
R--;
}
while(L < q[i].l){
cnt[a[L]]--;
if(cnt[a[L]] == 0) pos[a[L]] = 0;
if(cnt[a[L]] == 0) neg[offset - a[L]] = 0;
L++;
}
if(q[i].op == 1) //+
{
if(((pos>>q[i].x)&pos).any()){
ans[id] = 1;
}
else{
ans[id] = 0;
}
}
else if(q[i].op == 2){//-
if(((neg>>(offset-q[i].x))&pos).any()){
ans[id] = 1;
}
else{
ans[id] = 0;
}
}
else{
if(q[i].x == 0 && pos[0])
{
ans[id] = 1;
continue;
}
for(int j = 1; j*j <= q[i].x; j++)
{
if(q[i].x % j == 0 && pos[j] == 1&& pos[q[i].x/j] == 1){
ans[id] = 1;
break;
}
}
}
}
}
void output()
{
for(int i = 1; i <= m; i++){
puts(ans[i]?"yuno":"yumi");
}
}
int main()
{
input();
work();
output();
}