BZOJ4810: [Ynoi2017]由乃的玉米田
【传送门:BZOJ4810】
简要题意:
给出n个数,给出m种询问:
1 l r x判断是否在区间l到r中能选出两个数的差为x
2 l r x判断是否在区间l到r中能选出两个数的和为x
3 l r x判断是否在区间l到r中能选出两个数的乘积为x
其中选出的两个数可以相等
题解:
肯定得离线
用莫队吧(离线,第一时间就想到莫队)
第三个询问可以暴力求因子搞一搞
结果发现不会搞1和2
上网搜了搜,学了一波bitset
bitset简单来说可以当作一个二进制位来用,但是它并不需要二进制那样的庞大数据范围
而且赋值只需要像数组一样赋值
然后对于第1个操作,将当前bitset与当前的bitset向右移x位之后的bitset做一下and运算,假如有1,则说明成立
然后对于第2个操作,将用第二个bitset作为第一个bitset的取反,然后用反转bitset右移后和正bitset做一下and运算,如果有1,则说明成立(这个东西,自己脑补,也挺容易理解的)
参考代码:
#include<cstdio> #include<cstring> #include<algorithm> #include<cmath> #include<cstdlib> #include<bitset> using namespace std; bitset<110000> bs1,bs2; int a[110000]; int belong[110000]; struct node { int opt,l,r,x,d,id; }q[1100000];int n,m; bool cmp1(node n1,node n2) { if(belong[n1.l]<belong[n2.l]) return true; if(belong[n1.l]>belong[n2.l]) return false; if(belong[n1.l]==belong[n2.l]) { if(n1.r<n2.r) return true; if(n1.r>n2.r) return false; } return false; } bool cmp2(node n1,node n2) { return n1.id<n2.id; } int sum[110000]; void add(int x) { sum[x]++; if(sum[x]==1) bs1[x]=1,bs2[n-x+1]=1; } void del(int x) { sum[x]--; if(sum[x]==0) bs1[x]=0,bs2[n-x+1]=0; } int solve1(int x) { if(((bs1)&(bs1>>x)).any()==true) return 1; else return 0; } int solve2(int x) { if(((bs1)&(bs2>>(n-x+1))).any()==true) return 1; else return 0; } int solve3(int x) { int t=int(sqrt(x+1)); for(int i=1;i<=t;i++) if(x%i==0&&bs1[i]==1&&bs1[x/i]==1) return 1; return 0; } int main() { scanf("%d%d",&n,&m); for(int i=1;i<=n;i++) scanf("%d",&a[i]); int block=int(sqrt(n)); for(int i=1;i<=n;i++) { int t=(i-1)/block+1; belong[i]=t; } for(int i=1;i<=m;i++) { scanf("%d%d%d%d",&q[i].opt,&q[i].l,&q[i].r,&q[i].x); q[i].id=i; } sort(q+1,q+m+1,cmp1); int l=1,r=0; memset(sum,0,sizeof(sum)); bs1.reset();bs2.reset(); for(int i=1;i<=m;i++) { while(l>q[i].l){l--;add(a[l]);} while(l<q[i].l){del(a[l]);l++;} while(r>q[i].r){del(a[r]);r--;} while(r<q[i].r){r++;add(a[r]);} if(q[i].opt==1) q[i].d=solve1(q[i].x); if(q[i].opt==2) q[i].d=solve2(q[i].x); if(q[i].opt==3) q[i].d=solve3(q[i].x); } sort(q+1,q+m+1,cmp2); for(int i=1;i<=m;i++) if(q[i].d==1) printf("yuno\n"); else printf("yumi\n"); return 0; }
渺渺时空,茫茫人海,与君相遇,幸甚幸甚