• 洛谷 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;
    }
    
    
  • 相关阅读:
    Vue2020
    Vue2020
    Vue v-model双向数据绑定 的实现
    TCP 粘包
    黑幕模板
    STL总结与例子
    中缀表达式转后缀表达式
    php 转换数组里的时间戳
    gorm踩过的坑
    WxJava使用lettuce客户端的redis实现微信access_token等接口重复利用
  • 原文地址:https://www.cnblogs.com/zzhzzh123/p/13386005.html
Copyright © 2020-2023  润新知