[BZOJ4810][YNOI2017]由乃的玉米田(莫队+bitset)
莫队,cnt数组记录每个数的个数,bitset b1[i]记录数i是否出现过,b2[i]记录数M-i是否出现过。
减法:((b1>>x)&b1).any()。
加法:(((b2>>(M-x))&b1).any()。
乘法:若存在一定有一个数<=sqrt(1e5),枚举即可。
复杂度:$O(n\sqrt{n}(\frac{A}{\omega}+\sqrt{A}))$ 无法理解这个复杂度为什么能过。
1 #include<cstdio> 2 #include<bitset> 3 #include<algorithm> 4 #define rep(i,l,r) for (int i=(l); i<=(r); i++) 5 using namespace std; 6 7 const int N=100010,M=100000,B=320; 8 bool ans[N]; 9 int n,m,tot,a[N],bel[N],cnt[N]; 10 bitset<M>b1,b2; 11 struct Q{ int op,l,r,x,id; }q[N]; 12 bool operator <(const Q &a,const Q &b){ return bel[a.l]==bel[b.l] ? a.r<b.r : bel[a.l]<bel[b.l]; } 13 14 void add(int x){ cnt[x]++; b1[x]=b2[M-x]=1; } 15 void del(int x){ cnt[x]--; if (!cnt[x]) b1[x]=b2[M-x]=0; } 16 17 int main(){ 18 freopen("bzoj4810.in","r",stdin); 19 freopen("bzoj4810.out","w",stdout); 20 scanf("%d%d",&n,&m); tot=(n-1)/B+1; 21 rep(i,1,n) scanf("%d",&a[i]),bel[i]=(i-1)/B+1; 22 rep(i,1,m) scanf("%d%d%d%d",&q[i].op,&q[i].l,&q[i].r,&q[i].x),q[i].id=i; 23 sort(q+1,q+m+1); 24 int L=1,R=0; 25 rep(i,1,m){ 26 int op=q[i].op,l=q[i].l,r=q[i].r,x=q[i].x; 27 while (R<r) add(a[++R]); 28 while (R>r) del(a[R--]); 29 while (L>l) add(a[--L]); 30 while (L<l) del(a[L++]); 31 if (op==1) ans[q[i].id]=((b1>>x)&b1).any(); 32 if (op==2) ans[q[i].id]=((b2>>(M-x))&b1).any(); 33 if (op==3){ 34 bool fl=0; 35 rep(j,1,min(500,x)) if (b1[j] && b1[x/j] && x%j==0) { fl=1; break; } 36 ans[q[i].id]=fl; 37 } 38 } 39 rep(i,1,m) puts(ans[i] ? "yuno" : "yumi"); 40 return 0; 41 }