https://www.luogu.org/wiki/show?name=%E9%A2%98%E8%A7%A3+P3674
莫队算法+bitset维护
bitset真是个好东西.
考虑减的情况,
则ai-aj=x,ai=aj+x,l≤i,j≤r
所以,维护一个bitset s1满足s1&(s1<<x)>0有解
对于加的情况同理.
ai+aj=x,ai=x-aj,ai=x+(-aj),ai=(x-N)+(N-aj).[N,为任意常数,满足N-aj>=0即可]
所以,维护两个bitset s1和s2
s1存ai,s2存(N-ai)
满足s1&(s2>>(N-x))>0有解
对于乘的情况
O(√x)的效率的枚举x的因子,判断是否在bitset内
复杂度O( n( sqrt( n ) + c / 64 ) )
#include<stdio.h> #include<math.h> #include<bitset> #include<algorithm> #define FOR(i,s,t) for(register int i=s;i<=t;++i) const int N=100000; std::bitset<N+5>s1,s2; int c[N+5],a[N+5],ans[N+5]; inline void add(int x){if(!c[x])s1[x]=1,s2[N-x]=1;++c[x];} inline void del(int x){--c[x];if(!c[x])s1[x]=0,s2[N-x]=0;} int n,m,blo,l,r; struct question{ int ty,l,r,x,id; inline bool operator<(question A)const{ return l/blo<A.l/blo||(l/blo==A.l/blo&&r/blo<A.r/blo); } }q[N+5]; inline int read(){ char c;while(c=getchar(),c==' '||c==' ');int data=c-48; while(c=getchar(),c>='0'&&c<='9')data=(data<<1)+(data<<3)+c-48;return data; } int main(){ scanf("%d%d",&n,&m); blo=sqrt(n); FOR(i,1,n)scanf("%d",a+i); FOR(i,1,m)scanf("%d%d%d%d",&q[i].ty,&q[i].l,&q[i].r,&q[i].x),q[i].id=i; std::sort(q+1,q+m+1); r=0,l=1; FOR(i,1,m){ while(l<q[i].l)del(a[l++]); while(q[i].l<l)add(a[--l]); while(r<q[i].r)add(a[++r]); while(q[i].r<r)del(a[r--]); if(q[i].ty==1) if((s1&(s1<<q[i].x)).any()) ans[q[i].id]=1; if(q[i].ty==2) if((s1&(s2>>(N-q[i].x))).any()) ans[q[i].id]=1; if(q[i].ty==3){ for(register int j=1;j*j<=q[i].x;++j) if(q[i].x%j==0&&s1[j]&&s1[q[i].x/j]){ ans[q[i].id]=1; break; } } } FOR(i,1,m)puts(ans[i]?"hana":"bi"); return 0; }
丢张人渣的本愿图[逃]