P5355-[Ynoi2017]由乃的玉米田【莫队,bitset,根号分治】
正題
題目鏈接:https://www.luogu.com.cn/problem/P5355
 順帶一提的是P3674 小清新人渣的本愿是這題的弱化版,提交就可以A
題目大意
nnn個數字,詢問
aaa和bbb可以是同一個數。
解題思路
下面默認n,mn,mn,m同級
 莫隊的話修改是O(nn)O(n\sqrt n)O(nn?)次的但是詢問是O(n)O(n)O(n)次的所以詢問處可以操作一波。
對于前兩個操作,開兩個bitsetbitsetbitset,b1xb1_xb1x?表示是否有xxx這一個數,b2xb2_xb2x?表示是否有N?xN-xN?x這個數。
 那么對于詢問a+b=xa+b=xa+b=x就是詢問(b1<<x)&b1(b1<<x)\& b1(b1<<x)&b1是否有值,詢問a?b=xa-b=xa?b=x就是詢問(b1<<(N?x))&b2(b1<<(N-x))\&b2(b1<<(N?x))&b2是否有值。上面的十分顯然,并且bitsetbitsetbitset跑的也很快,可以通過。
然后詢問a?b=xa*b=xa?b=x的話我們可以直接枚舉xxx的約數即可,這樣是O(n)O(\sqrt n)O(n?)的
對于詢問a/b=xa/b=xa/b=x的我們需要考慮根號分治,對于大于n\sqrt nn?的我們就直接在莫隊的時候枚舉xxx的所有倍數。對于小于n\sqrt nn?的因為只有n\sqrt nn?個所以我們對于每個值可以O(n)O(n)O(n)搞。
假設目前為xxx,設resires_iresi?表示以iii為右端點且有答案時最大的左端點位置,那么我們可以處理一個lastilast_ilasti?表示上次iii出現的位置,然后沒出用aia_iai?和lastlastlast數組來更新resresres即可。
codecodecode
#include<cstdio> #include<cstring> #include<algorithm> #include<vector> #include<bitset> using namespace std; const int N=1e5+10,T=300; struct node{int op,l,r,x,id; }q[N]; bitset<N> b1,b2; int n,m,a[N],v[N],last[N],res[N]; bool ans[N];vector<int> qt[T+10]; bool cmp(node x,node y) {return x.l/T==y.l/T?(x.r<y.r):(x.l<y.l);} void add(int x){if(!v[x])b1[x]=1,b2[100000-x]=1;v[x]++;return; } void del(int x){if(v[x]==1)b1[x]=0,b2[100000-x]=0;v[x]--;return; } int main() {scanf("%d%d",&n,&m);for(int i=1;i<=n;i++)scanf("%d",&a[i]);for(int i=1;i<=m;i++){q[i].id=i;scanf("%d%d%d%d",&q[i].op,&q[i].l,&q[i].r,&q[i].x);}sort(q+1,q+1+m,cmp);int l=1,r=0;for(int i=1;i<=m;i++){if(q[i].op==4&&q[i].x<=T){qt[q[i].x].push_back(i);continue;}while(l<q[i].l)del(a[l]),l++;while(l>q[i].l)l--,add(a[l]);while(r<q[i].r)r++,add(a[r]);while(r>q[i].r)del(a[r]),r--;int x=q[i].x;if(q[i].op==1)ans[q[i].id]=(b1&(b1<<x)).any();else if(q[i].op==2)ans[q[i].id]=((b1<<(100000-x))&b2).any();else if(q[i].op==3){for(int j=1;j*j<=x;j++)if(x%j==0&&v[j]&&v[x/j]){ans[q[i].id]=1;break;}}else{for(int j=1;j*x<=1e5;j++)if(v[j]&&v[j*x]){ans[q[i].id]=1;break;}}}for(int x=1;x<=T;x++){if(qt[x].empty())continue;memset(last,0,sizeof(last));for(int i=1;i<=n;i++){last[a[i]]=i;res[i]=res[i-1];if(x*a[i]<=1e5)res[i]=max(res[i],last[x*a[i]]);if(a[i]%x==0)res[i]=max(res[i],last[x/a[i]]);}for(int p=0;p<qt[x].size();p++){int i=qt[x][p];ans[q[i].id]=(q[i].l<=res[q[i].r]);}}for(int i=1;i<=m;i++)puts(ans[i]?"hana":"bi");return 0; }總結
以上是生活随笔為你收集整理的P5355-[Ynoi2017]由乃的玉米田【莫队,bitset,根号分治】的全部內容,希望文章能夠幫你解決所遇到的問題。
                            
                        - 上一篇: P6348-[PA2011]Journe
 - 下一篇: 京东店铺装修,如果将商品分类采集并下载到