【洛谷 P3674】 小清新人渣的本願(bitset,莫隊)

題目鏈接
因爲每個數都是\(10^5\)以內,考慮直接用\(bitset\)維護。
\(a-b=x\),其實就是看是否有\(p\)\(p+x\)同時存在,直接\(bitset\)移位按位與一下就好了。
\(a+b=x\),這個直接搞不好搞,所以考慮轉化。
\[a-(N-b)=a+b-N=x-N\]
其中\(N\)爲一個常數,令\(f(x)=N-x\),則有
\[f(b)-f(x)=a\]
於是再開個\(bitset\)維護\(f(x)\),然後就很顯然了。
\(a*b=x\),這個顯然沒法用\(bitset\)做,但是\(x\)的因數個數是\(\sqrt x\)級別的,所以直接暴力枚舉因數就行了。
爲了防止負數的出現,上文中的\(N\)取題中的值域上限\(10^5\)
最後套上莫隊模板。

#include <cstdio>
#include <algorithm>
#include <cstring>
#include <bitset>
#include <cmath>
#include <iostream>
using namespace std;
const int MAXN = 100010;
bitset <MAXN> p1, p2;
int n, m, a[MAXN];
inline int read(){
    int s = 0;
    char ch = getchar();
    while(ch < '0' || ch > '9') ch = getchar();
    while(ch >= '0' && ch <= '9'){ s = s * 10 + ch - '0'; ch = getchar(); }
    return s;
}
int Q, v[MAXN], ans[MAXN];
struct ask{
    int type, l, r, c, id;
    int operator < (const ask A) const{
        return l / Q == A.l / Q ? r < A.r : l < A.l;
    }
}q[MAXN];
void add(int x){
    ++v[a[x]];
    p1[a[x]] = p2[100000 - a[x]] = 1;
}
void del(int x){
    if(!--v[a[x]])
        p1[a[x]] = p2[100000 - a[x]] = 0;
}
int main(){
    n = read(); m = read(); Q = sqrt(n);
    for(int i = 1; i <= n; ++i)
        a[i] = read();
    for(int i = 1; i <= m; ++i)
        scanf("%d%d%d%d", &q[i].type, &q[i].l, &q[i].r, &q[i].c), q[i].id = i;
    sort(q + 1, q + m + 1);
    int l = 1, r = 0;
    for(int i = 1; i <= m; ++i){
        while(r < q[i].r) add(++r);
        while(l > q[i].l) add(--l);
        while(r > q[i].r) del(r--);
        while(l < q[i].l) del(l++);
        if(q[i].type == 1){
            ans[q[i].id] = (p1 & (p1 >> q[i].c)).any();
        }else if(q[i].type == 2){
            ans[q[i].id] = (p1 & (p2 >> (100000 - q[i].c))).any();
        }else{
            if(!q[i].c) ans[q[i].id] = v[0];
            int sqr = sqrt(q[i].c);
            for(int j = 1; j <= sqr; ++j)
                if(q[i].c % j == 0)
                    if(v[j] && v[q[i].c / j]){
                        ans[q[i].id] = 1;
                        break;
                    }
        }
    }
    for(int i = 1; i <= m; ++i)
        printf("%s\n", ans[i] ? "hana" : "bi");
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章