题解: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;
}

浙公网安备 33010602011771号