P5355 [Ynoi2017] 由乃的玉米田 莫队 根号分治 数据结构
题意:
分析:
弱化版 : 小清新人渣的本愿
分操作考虑:
- 
加 or 减 本质就是查询区间内是否有一个数对,想了半天都没有想到有什么数据结构可以做,最后发现,竟然还有个 \(bitset\) 维护一个正着的 \(bitset\) 和一个反着的 \(bitset\) 就可以同时实现加减的操作 
- 
乘 最水的一个操作,\(O(\sqrt x)\)枚举因数 ,\(bitset\) 判断是否存在 
- 
除 可以转化成乘法,判断 \(a,ax\) 是否同时存在,当 \(a,b\) 很小的时候枚举倍数是 \(O(m/a)\) 的复杂度就不对了,但是我们发现对于值很小的时候,对于每一个询问,我们可以 \(O(n)\) 的扫一遍判断把每个值都存下来,一边扫一边判断它的倍数是否出现过 这样得到了两种做法,当 \(x>\sqrt{10000}\) 时枚举倍数不超过 \(O(\sqrt{10000})\) 次,当 \(x<\sqrt{100000}\) 时这样的数不超过 \(\sqrt{100000}\) 个,所以总复杂度不超过 \(O(n\sqrt m)\) 
代码:
#include<bits/stdc++.h>
#define pii pair<int,int>
#define mk(x,y) make_pair(x,y)
#define lc rt<<1
#define rc rt<<1|1
#define pb push_back
#define fir first
#define sec second
#define inl inline
#define reg register
using namespace std;
namespace zzc
{
	typedef long long ll;
	inline int read()
	{
		int x=0,f=1;char ch=getchar();
		while (!isdigit(ch)){if (ch=='-') f=-1;ch=getchar();}
		while (isdigit(ch)){x=x*10+ch-48;ch=getchar();}
		return x*f;
	}
	
	const int maxn = 1e5+5;
	const int sqr = 325;
	int n,m,blo,tot;
	int v[maxn],cnt[maxn],lst[maxn],colst[maxn],ans[maxn];
	vector<int> ql[sqr+5],qr[sqr+5],qi[sqr+5];
	bitset<maxn> bs1,bs2;
	
	struct que
	{
		int l,r,opt,x,id;
		bool operator <(const que &b)const
		{
			return (l/blo)==(b.l/blo)?((l/blo)&1?r<b.r:r>b.r):l<b.l;
		}
	}q[maxn];
	
	void ins(int x)
	{
		if(++cnt[x]==1) bs1[x]=1,bs2[100000-x]=1;
	}
	
	void del(int x)
	{
		if(--cnt[x]==0) bs1[x]=0,bs2[100000-x]=0;
	}
	
	bool query_mul(int x)
	{
		for(int i=1;i*i<=x;i++) if(x%i==0&&bs1[i]&&bs1[x/i]) return true;
		return false;
	}
	
	bool query_dev(int x)
	{
		for(int i=1;i*x<=100000;i++) if(bs1[i]&&bs1[i*x]) return true;
		return false;
	}
	
	void mo()
	{
		int l=1,r=0;
		for(int i=1;i<=tot;i++)
		{
			while(l>q[i].l) ins(v[--l]);
			while(r<q[i].r) ins(v[++r]);
			while(l<q[i].l) del(v[l++]);
			while(r>q[i].r) del(v[r--]);
			if(q[i].opt==1) ans[q[i].id]=((bs1<<q[i].x)&bs1).any();
			else if(q[i].opt==2) ans[q[i].id]=((bs1<<(100000-q[i].x))&bs2).any();
			else if(q[i].opt==3) ans[q[i].id]=query_mul(q[i].x);
			else ans[q[i].id]=query_dev(q[i].x);
		}
	}
	
	void solve()
	{
		for(int x=1;x<=sqr;x++)
		{
			if(ql[x].empty()) continue;
			int l=0;
			for(int i=1;i<=n;i++)
			{
				int y=v[i];
				lst[y]=i;
				if(x*y<=100000) l=max(l,lst[x*y]);
				if(y%x==0) l=max(l,lst[y/x]);
				colst[i]=l;
			}
			for(int i=0,j=ql[x].size();i<j;i++) ans[qi[x][i]]=(ql[x][i]<=colst[qr[x][i]]);
			memset(lst,0,sizeof(lst));
			memset(colst,0,sizeof(colst));
		}
	}
	
	void work()
	{
		int opt,l,r,c;
		n=read();m=read();blo=n/sqrt(m);
		for(int i=1;i<=n;i++) v[i]=read();
		for(int i=1;i<=m;i++)
		{
			opt=read();l=read();r=read();c=read();
			if(opt==4&&c<=sqr) ql[c].pb(l),qr[c].pb(r),qi[c].pb(i);
			else 
			{
				q[++tot].opt=opt;
				q[tot].id=i;
				q[tot].l=l;
				q[tot].r=r;
				q[tot].x=c;
			}
		}
		sort(q+1,q+tot+1);
		mo();
		solve();
		for(int i=1;i<=m;i++) if(ans[i]) puts("yuno");else puts("yumi");
	}
}
int main()
{
	zzc::work();
	return 0;
}

 
                
            
         浙公网安备 33010602011771号
浙公网安备 33010602011771号