luogu 3674

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和s

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;
}

丢张人渣的本愿图[逃]

原文地址:https://www.cnblogs.com/Stump/p/7905915.html