洛谷P3674 【小清新人渣的本愿】

\(\text{bitset}\)神题啊。

正文部分

首先你得想到这题得用\(\text{bitset}\)来做。
我们先设一个\(\text{bitset,zhe}\)其第\(i\)位表示\(i\)这个数字有没有出现。
我们再设一个\(\text{bitset,rev}\)其第\(i\)位表示\(n-i\)是否出现。
接着我们看询问:
对于加法:我们只需要将\(\text{zhe}\)\(\text{zhe<<x}\)做一下\(and\)运算就好了。
对于减法:
我们先推一下式子:
\(z+y=x\)
\(n-(n-y)+z=x\)
\(z-(n-y)=x-n\)
这样就和加法形式一样了
乘法:乘法没什么技巧,直接枚举因数
对于询问的话其实我们用一个莫队滚一下就好了

My code

#include <bits/stdc++.h>
#define il inline
#define gc getchar
#define isd(c) (c >= '0' && c <= '9')
const int MAXN = 1e5 + 10;
const int MAXM = MAXN;
using namespace std;
il int read() {
    int res = 0;char c;bool sign = 0;
    for(c = gc();!isd(c);c = gc()) sign |= c == '-';
    for(;isd(c);c = gc()) res = (res << 1) + (res << 3) + (c ^ 48);
    return sign ? -res : res;
}
int a[MAXN],bel[MAXN],cnt[MAXN];bool ans_arr[MAXM];
int n,m,i,j,k;
struct Questions {
    int opt,l,r,x,id;
    Questions() {opt = l = r = x = id = 0;}
    Questions(int _opt,int _l,int _r,int _x,int _id) {
        opt = _opt;l = _l;r = _r;x = _x;id = _id;
    }
}Query[MAXM];
bitset<MAXN>zhe,rev;
il bool cmp1(Questions a,Questions b) {
    if(bel[a.l] != bel[b.l]) return bel[a.l] < bel[b.l];
    else return a.r < b.r;
} 
il void add(int x) {
    int tmp = a[x];
    cnt[tmp]++;cnt[tmp] == 1 ? zhe[tmp] = 1,rev[n - tmp] = 1 : NULL;
}
il void del(int x) {
    int tmp = a[x];
    cnt[tmp]--;!cnt[tmp] ? zhe[tmp] = 0,rev[n - tmp] = 0 : NULL;
}
int main() { 
    n = read();m = read();
    for(int i = 1;i <= n;i++) a[i] = read();const int bls = (int)(sqrt(n));
    for(int i = 1;i <= m;i++) {
        int opt = read(),l = read(),r = read(),x = read();
        Query[i] = Questions(opt,l,r,x,i);
        bel[i] = (i - 1) / bls + 1;
    }   
    sort(Query + 1,Query + m + 1,cmp1);    
    int l = 1,r = 0;
    for(int _i = 1;_i <= m;_i++) {
        while(l > Query[_i].l) add(--l);
        while(r < Query[_i].r) add(++r);
        while(l < Query[_i].l) del(l++);
        while(r > Query[_i].r) del(r--);
        int x = Query[_i].x;
        switch(Query[_i].opt) {
            case 1: {
                if((zhe & (zhe << x)).any()) ans_arr[Query[_i].id] = 1;
                break;
            } 
            case 2: {
                if((zhe & (rev >> n - x)).any()) ans_arr[Query[_i].id] = 1;
                break;
            }
            case 3: {
                for(int i = 1;i <= (int)(sqrt(x));i++) {
                    if(x % i == 0) {
                        if(zhe[i] && zhe[x / i]) {
                            ans_arr[Query[_i].id] = 1;
                            break;
                        }
                    }
                }
                break;
            }
        }
    }
    for(int i = 1;i <= m;i++) {
        ans_arr[i] ? puts("hana") : puts("bi");
    }
    return 0;
}

猜你喜欢

转载自www.cnblogs.com/Sai0511/p/10360579.html