[bzoj4810][Ynoi2017]由乃的玉米田【bitset】【莫队】

【题目链接】
  https://www.lydsy.com/JudgeOnline/problem.php?id=4810
【题解】
  首先可以离线下来使用莫队,这样就知道了每个询问区间中每个数是否出现,将其压为一个bitset,记为 f f
  考虑如何询问:
  对于操作1:可行的条件是f^ f<<x f << x 不全为 0 0
  对于操作2:记g表示 f f 翻转后的结果(第i位于第(最高位-i)位替换),那么可行的条件是f^ g<<(x) g << ( 最 高 位 − x ) 不全为0。
  对于操作3:直接枚举 x x 的因数。
  时间复杂度O(NN+N2/64)
【代码】

/* - - - - - - - - - - - - - - -
    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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值