• P5355 [Ynoi2017] 由乃的玉米田 莫队 根号分治 数据结构


    题意:

    戳这里

    分析:

    弱化版 : 小清新人渣的本愿

    分操作考虑:

    1. 加 or 减

      本质就是查询区间内是否有一个数对,想了半天都没有想到有什么数据结构可以做,最后发现,竟然还有个 (bitset)

      维护一个正着的 (bitset) 和一个反着的 (bitset) 就可以同时实现加减的操作

    2. 最水的一个操作,(O(sqrt x))枚举因数 ,(bitset) 判断是否存在

    3. 可以转化成乘法,判断 (a,ax) 是否同时存在,当 (a,b) 很小的时候枚举倍数是 (O(m/a)) 的复杂度就不对了,但是我们发现对于值很小的时候,对于每一个询问,我们可以 (O(n)) 的扫一遍判断把每个值都存下来,一边扫一边判断它的倍数是否出现过

      这样得到了两种做法,当 (x>sqrt{10000}) 时枚举倍数不超过 (O(sqrt{10000})) 次,当 (x<sqrt{100000}) 时这样的数不超过 (sqrt{100000}) 个,所以总复杂度不超过 (O(nsqrt 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;
    }
    
    
  • 相关阅读:
    python 杂谈
    python: list转字符串
    dataframe
    time模块
    python 调试器
    BAT机器学习面试1000题系列(41-45题)
    join()函数
    value_counts()
    模型评估
    04flask_scripts使用
  • 原文地址:https://www.cnblogs.com/youth518/p/14297126.html
Copyright © 2020-2023  润新知