由乃的玉米田

由乃的玉米田

给你一个序列 aaa,长度为 nnn,有 mmm 次操作,每次询问一个区间是否可以选出两个数它们的差为 xxx,或者询问一个区间是否可以选出两个数它们的和为 xxx,或者询问一个区间是否可以选出两个数它们的乘积为 xxx ,或者询问一个区间是否可以选出两个数它们的商为 xxx(没有余数) ,这四个操作分别为操作 1,2,3,41,2,3,41,2,3,4。

选出的这两个数可以是同一个位置的数。

数据范围(1e5)

莫队+bitset维护每个值是否出现

注意0的特判情况

减法:

a-b=x

a=b+x;

于是按位与(bit&(bit<<x))若有值则可行

加法:

a-(n-b)=x-n

a=(n-b)-x+n

于是莫队时再维护一个反的序列

(ans=(bit&(bit2>>n-x)).any())

乘法:

(sqrt n)暴力判

整除:

数据分块

(x>sqrt n)暴力判

(x<sqrt n)每个x的询问集中单独算,移右端点算左端点,树状数组维护

时间复杂度(O(nsqrt nlog n+frac{n^2}w))

//starusc
/*
数据不清空,爆零两行泪。
多测不读完,爆零两行泪。
边界不特判,爆零两行泪。
贪心不证明,爆零两行泪。
D P 顺序错,爆零两行泪。
大小少等号,爆零两行泪。
变量不统一,爆零两行泪。
越界不判断,爆零两行泪。
调试不注释,爆零两行泪。
溢出不 l l,爆零两行泪。
*/
#include<bits/stdc++.h>
using namespace std;
inline int read() {
	int x=0,f=1;
	char c=getchar();
	while(!isdigit(c)) {
		if(c=='-')f=-1;
		c=getchar();
	}
	while(isdigit(c)) {
		x=(x<<1)+(x<<3)+(c^48);
		c=getchar();
	}
	return f==1?x:-x;
}
const int N = 1e5+4, B = 400;
int n, m, a[N], ans[N], cnt[N];
struct ques {
	int op, l, r, v, id;
} q[N];
inline bool comp (const ques &x, const ques &y) {
	return x.l/B == y.l/B ? (((x.l/B)&1) ? x.r < y.r : x.r > y.r) : x.l/B < y.l/B;
}
bitset<N>b,rb;
inline bool comp_2(const ques &x,const ques &y){
	return x.r<y.r;
}
int t[N],tmp[N];
vector<ques>que[B];
inline void add(int x,int v){
	for(;x<=n;x+=x&-x)t[x]+=v;
}
inline int ask(int x){
	int ret=0;
	for(;x;x-=x&-x)ret+=t[x];
	return ret;
}
inline void solve(int c){
	if(que[c].empty())return;
	sort(que[c].begin(),que[c].end(),comp_2);
	int nw=1;
	for(auto v:que[c]){
		while(nw<=n&&nw<=v.r){
			if(tmp[a[nw]]){
				add(1,1);add(tmp[a[nw]]+1,-1);
			}
			if(a[nw]*c<=N-4)tmp[a[nw]*c]=nw;
			if(a[nw]%c==0)tmp[a[nw]/c]=nw;
			nw++;
		}
		ans[v.id]|=(ask(v.l)>0);
	}
	memset(t,0,sizeof(t));
	memset(tmp,0,sizeof(tmp));
}
int main() {
	n = read();
	m = read();
	for(int i = 1; i <= n; ++i) a[i] = read();
	for(int i = 1; i <= m; ++i) {
		q[i].op = read();
		q[i].id = i;
		q[i].l = read();
		q[i].r = read();
		q[i].v = read();
	}
	sort(q + 1, q + m + 1, comp);
	for(int i = 1, nl = 1, nr = 0; i <=m ; ++i) {
		while(nr < q[i].r) {
			nr++;
			if(!cnt[a[nr]]) {
				b[a[nr]] = 1;
				rb[N-4-a[nr]] = 1;
			}
			cnt[a[nr]]++;
		}
		while(nl > q[i].l) {
			nl--;
			if(!cnt[a[nl]]) {
				b[a[nl]] = 1;
				rb[N-4-a[nl]] = 1;
			}
			cnt[a[nl]]++;
		}
		while(nr > q[i].r) {
			cnt[a[nr]]--;
			if(!cnt[a[nr]]) {
				b[a[nr]] = 0;
				rb[N-4-a[nr]] = 0;
			}
			nr--;
		}
		while(nl < q[i].l) {
			cnt[a[nl]]--;
			if(!cnt[a[nl]]) {
				b[a[nl]] =0 ;
				rb[N-4-a[nl]] =0 ;
			}
			nl++;
		}
		if(q[i].op == 1) ans[q[i].id] = (b & (b << q[i].v)).any();
		else if(q[i].op == 2) ans[q[i].id] = ((b << N-4-q[i].v) & rb).any();
		else if(q[i].op == 3) {
			if(!q[i].v)ans[q[i].id]=b[0];
			else for(int j = 1; j * j <= q[i].v; ++j) {
				if(q[i].v % j)continue;
				if(b[j] && b[q[i].v / j]) {
					ans[q[i].id] = 1;
					break;
				}
			}
		}
		else{
			if(!q[i].v)ans[q[i].id]=b[0]&&b.count()>1;
			else if(q[i].v==1)ans[q[i].id]=(b.count()-b[0])>0;
			else if(q[i].v>=B){
				for(int j=1,j2=q[i].v;j2<=N-4;j++,j2+=q[i].v)
					if(b[j]&&b[j2]){
						ans[q[i].id]=1;
						break;
					}
			}	
			else que[q[i].v].push_back(q[i]);
		}
	}
	for(int i=2;i<B;i++)solve(i);
	for(int i = 1; i <= m; ++i)
		puts(ans[i] ? "yuno" : "yumi");
	return (0-0);
}

原文地址:https://www.cnblogs.com/aurora2004/p/12989430.html