Loading

题解:P8327 [COCI2021-2022#5] Radio

我们考虑根号分治,每个数只有 \(1\) 个大于 \(\sqrt n=1000\) 的质因数,而 \(1000\) 以内的质因数有 \(168\) 个。

注意到 \(168\) 很小,我们心生邪念想到 \(\frac{168}{\omega}\) 几乎是常数,于是上一个线段树套 bitset 维护 \(1000\) 以内的质因数,区间查询是否有两位置 bitset 有交,维护区间内的 bitset 并即可。

然后对于大于 \(1000\) 的质因数,由于每个数对应 \(1\) 个,考虑对每个质因数维护。我们设 \(f_x\)\(x\) 的大于 \(1000\) 的质因数,\(nxt_x\)\(x\) 之后第一个 \(y\) 满足 \(f_x=f_y\)。每种 \(f\) 开一个 set 维护每位置的 \(nxt\),线段树维护区间 min。

时间复杂度 \(O(q\frac{\sqrt n}{\ln n}+q\log n+q\frac{\sqrt n\log n}{\omega\ln n})\),但是 \(\frac{\sqrt n}{\omega\ln n}\approx O(1)\)

#include<map>
#include<set>
#include<cmath>
#include<ctime>
#include<queue>
#include<stack>
#include<cstdio>
#include<vector>
#include<string>
#include<bitset>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
using namespace std;
const int MAXN=1e6+10;
const int MAXM=1e3+10;
const int INF=0x3f3f3f3f;
const long long LINF=0x3f3f3f3f3f3f3f3f;
int n,q;
bool ins[MAXN];
int cnt=0;
int prime[MAXM],bac[MAXM];
bitset <MAXM> unp;
inline void seive(){
    unp[0]=true;
    unp[1]=true;
    for(int i=2;i<=1000;i++)
    {
        if(unp[i]){
            continue;
        }
        cnt++;
        prime[cnt]=i;
        bac[i]=cnt;
        for(int j=i*i;j<=1000;j+=i)
        {
            unp[j]=true;
        }
    }
}
namespace zkw{
    int m;
    bitset <170> prm[MAXN<<2];
    bool res[MAXN<<2];
    #define ls(x) (x<<1)
    #define rs(x) (x<<1|1)
    inline void push_up(int x){
        if(res[ls(x)]||res[rs(x)]){
            res[x]=true;
            return ;
        }
        if((prm[ls(x)]&prm[rs(x)]).any()){
            res[x]=true;
            return ;
        }
        res[x]=false;
        prm[x]=prm[ls(x)]|prm[rs(x)];
    }
    inline void build(){
        m=1<<(__lg(n)+1);
    }
    inline void modify(int pos,bitset <170> val){
        pos+=m;
        prm[pos]=val;
        for(pos>>=1;pos;pos>>=1)
        {
            push_up(pos);
        }
    }
    inline bool query(int l,int r){
        bitset <170> now;
        for(l+=m-1,r+=m+1;l^r^1;l>>=1,r>>=1)
        {
            if(~l&1){
                if(res[l^1]||(now&prm[l^1]).any()){
                    return true;
                }
                now|=prm[l^1];
            }
            if(r&1){
                if(res[r^1]||(now&prm[r^1]).any()){
                    return true;
                }
                now|=prm[r^1];
            }
        }
        return false;
    }
}
int b[MAXN];
set <int> big[MAXN];
int nxt[MAXN];
namespace zkw_min{
    int m;
    bitset <170> prm[MAXN<<2];
    int minv[MAXN<<2];
    #define ls(x) (x<<1)
    #define rs(x) (x<<1|1)
    inline void push_up(int x){
        minv[x]=min(minv[ls(x)],minv[rs(x)]);
    }
    inline void build(){
        m=1<<(__lg(n)+1);
        for(int i=1;i<=m+n;i++)
        {
            minv[i]=n+1;
        }
    }
    inline void modify(int pos){
        int val=nxt[pos];
        pos+=m;
        minv[pos]=val;
        for(pos>>=1;pos;pos>>=1)
        {
            push_up(pos);
        }
    }
    inline int query(int l,int r){
        int res=n+1;
        for(l+=m-1,r+=m+1;l^r^1;l>>=1,r>>=1)
        {
            if(~l&1){
                res=min(res,minv[l^1]);
            }
            if(r&1){
                res=min(res,minv[r^1]);
            }
        }
        return res;
    }
}
inline void add(int x){
    int y=x;
    bitset <170> res;
    for(int i=1;i<=cnt&&prime[i]<=x;i++)
    {
        if(y%prime[i]==0){
            while(y%prime[i]==0)
            {
                y/=prime[i];
            }
            res[i]=true;
        }
    }
    zkw::modify(x,res);
    b[x]=y;
    if(y>1){
        set <int>::iterator it=big[y].insert(x).first;
        if(it!=big[y].begin()){
            int p=*prev(it);
            nxt[p]=x;
            zkw_min::modify(p);
        }
        if(next(it)!=big[y].end()){
            nxt[x]=*next(it);
            zkw_min::modify(x);
        }
    }
}
inline void del(int x){
    int y=b[x];
    zkw::modify(x,bitset <170>());
    if(y>1){
        set <int>::iterator it=big[y].find(x);
        if(it!=big[y].begin()){
            int p=*prev(it);
            if(next(it)!=big[y].end()){
                nxt[p]=*next(it);
            }
            else{
                nxt[p]=n+1;
            }
            zkw_min::modify(p);
        }
        nxt[x]=n+1;
        zkw_min::modify(x);
        big[y].erase(it);
    }
}
signed main(){
    seive();
    scanf("%d%d",&n,&q);
    zkw::build();
    for(int i=1;i<=n;i++)
    {
        nxt[i]=n+1;
    }
    zkw_min::build();
    while(q--)
    {
        char opt;
        scanf(" %c",&opt);
        if(opt=='S'){
            int x;
            scanf("%d",&x);
            if(!ins[x]){
                add(x);
            }
            else{
                del(x);
            }
            ins[x]=!ins[x];
        }
        else{
            int l,r;
            scanf("%d%d",&l,&r);
            if(zkw::query(l,r)||zkw_min::query(l,r)<=r){
                puts("DA");
            }
            else{
                puts("NE");
            }
        }
    }
    return 0;
}
posted @ 2025-02-09 07:15  Mathew_Miao  阅读(10)  评论(0)    收藏  举报