洛谷 P3674 小清新人渣的本愿

题目链接

求给定区间内有无两个数的和/差/积为给定的数(两个数可相同)。

首先操作可离线,范围又只有\(10^5\),还是区间问题,又没有什么数据结构维护,那大概就是莫队吧。

我们维护每种数出现次数,记为\(sum_i\)

然后开两个bitset当作bool 数组用,分别统计\(i\)\(100000 - i\)的值是否存在。

求差:

\[a - b = x \\ a = b + x\\ \]

ans = (bitset1 & (bitset1 << x)).any();

求和:

\[a + b = x \\ a + (100000 - x)= (100000 - b) \\ \]

ans = (bitset2 & (bitset1 << (100000 - x))).any();

求积:
直接对\(x\)分解因数,枚举所有\(\leq \sqrt(x)\)的因数,然后判断\(i\)\(\frac{i}{x}\)是否存在与bitset1中


#include<bits/stdc++.h>
using namespace std;

const int N = 100050;

int n,m;
int a[N];

struct OP{
    int opt,l,r,v,id;
}q[N];
int belong[N],block;
bool cmp(OP a,OP b){
    return (belong[a.l] ^ belong[b.l]) ? (belong[a.l] < belong[b.l]) : ( (belong[a.l] & 1) ? a.r < b.r : a.r > b.r );
}

bitset<N> mp1,mp2;//mp1[i] = mp2[100000 - i] 表示i有没有
int sum[N];

int ans[N];

void add(int x){
    ++ sum[a[x]];
    if(sum[a[x]] == 1) mp1[a[x]] = mp2[100000 - a[x]] = 1;
}
void del(int x){
    -- sum[a[x]];
    if(sum[a[x]] == 0) mp1[a[x]] = mp2[100000 - a[x]] = 0;
}

int main(){
    scanf("%d%d",&n,&m);
    for(int i = 1; i <= n; ++ i) scanf("%d",&a[i]);
    
    for(int i = 1; i <= m; ++ i){
        scanf("%d%d%d%d",&q[i].opt,&q[i].l,&q[i].r,&q[i].v);
        q[i].id = i;
    }
    
    block = ceil(sqrt(n));
    for(int i = 1; i <= n; ++ i) belong[i] = (i - 1) / block + 1;
    sort(q + 1, q + m + 1, cmp);
    
    int L = 1, R = 0;
    for(int i = 1; i <= m; ++ i){
        while(L < q[i].l) del(L ++);
        while(L > q[i].l) add(-- L);
        while(R < q[i].r) add(++ R);
        while(R > q[i].r) del(R --);
        
        if(q[i].opt == 1){//a - b = v -> a = b + v
            ans[q[i].id] = (mp1 & (mp1 << q[i].v)).any();
        }
        if(q[i].opt == 2){//a + b = v -> a = v - b -> a = (100000 - b) - (100000 - v) 
            ans[q[i].id] = (mp1 & (mp2 >> (100000 - q[i].v)) ).any();
        }
        if(q[i].opt == 3){
            for(int j = 1; 1ll * j * j <= q[i].v; ++ j){
                if(q[i].v % j) continue;
                
                int x = j, y = q[i].v / j;
                ans[q[i].id] = mp1[x] & mp1[y];
                if(ans[q[i].id]) break;
            }
        }
        /*if(a[i].opt == 4){
            
        }*/
    }
    
    for(int i = 1; i <= m; ++ i) 
    puts(ans[i] ? "hana" : "bi" );
    
    return 0;
}

posted @ 2020-07-27 16:13  zhuzihan  阅读(128)  评论(0编辑  收藏  举报