bzoj 4810 [Ynoi2017]由乃的玉米田(莫队+bitset)

来源:互联网 发布:c 高级编程 第7版 pdf 编辑:程序博客网 时间:2024/05/18 17:25

题意:给一个长度为n的序列,然后有m次询问,
  1)[l,r]这个区间内能否找到两个数(可以是同一个位置的数)满足a-b=x。
  2)[l,r]这个区间内能否找到两个数(可以是同一个位置的数)满足a+b=x。
  3)[l,r]这个区间内能否找到两个数(可以是同一个位置的数)满足a * b=x。
所有数据均不超过十万。

思路:
  很容易想到用莫队后加上一个bitset的优化来处理第一个查询,用bitset维护区间中有哪些数字a[i],然后a-b=x等价于a=b+x,将bitset位移即可。对于第二个查询需要一个转换,a+b=x,a=-b+x,a=limit-b+x-limit。然后维护第二个bitset是limit-a[i]的,然后就能看作是a=bitset2 - (limit - x),就和之前那个询问一样了。对于第三个询问,直接暴力枚举因子即可,m次查询,每次枚举只有sqrt(x)。
  综上复杂度为O(max(n2/32,nn))

#include <bits/stdc++.h>using namespace std;const int maxn = 100000 + 100;const int limit = 100000 + 5;int a[maxn], b[maxn], ans[maxn], times[maxn];bitset<maxn>f, g, temp;struct node{    int op, l, r, x, block, id;    bool operator < (const node &other)const    {        return block < other.block || (block == other.block && r < other.r);    }}q[maxn];void ins(int p){    times[a[p]]++;    if(times[a[p]] == 1)  f[a[p]] = 1, g[b[p]] = 1;}void era(int p){    times[a[p]]--;    if(times[a[p]] == 0)  f[a[p]] = 0, g[b[p]] = 0;}bool query(int qidx){    if(q[qidx].op == 1)    {        temp = f;        temp >>= q[qidx].x;        temp &= f;        if(temp.count())    return true;    }    else if(q[qidx].op == 2)    {        temp = g;        temp >>= (limit - q[qidx].x);        temp &= f;        if(temp.count())    return true;    }    else    {        int num = q[qidx].x;        for(int i = 1; i <= sqrt(num); i++)        {            if(num % i == 0 && f[i] && f[num/i])return true;        }    }    return false;}int main(){    int n, m;    scanf("%d%d", &n, &m);    for(int i = 1; i <= n; i++) scanf("%d", &a[i]), b[i] = limit - a[i];    int len = sqrt(m);    for(int i = 0; i < m; i++)    {        scanf("%d%d%d%d", &q[i].op, &q[i].l, &q[i].r, &q[i].x);        q[i].block = q[i].l / len, q[i].id = i;    }    sort(q, q + m);    int ll = q[0].l, rr = q[0].l-1;    for(int i = 0; i < m; i++)    {        while(q[i].r > rr)  ins(++rr);        while(q[i].l < ll)  ins(--ll);        while(q[i].r < rr)  era(rr--);        while(q[i].l > ll)  era(ll++);        ans[q[i].id] = query(i);    }    for(int i = 0; i < m; i++)  puts(ans[i] ? "yuno" : "yumi");    return 0;}