CF1340F Nastya and CBS
阿新 • • 發佈:2020-07-14
題意:
\(n,k,q \leq 10^5\)。
題解:考慮到暴力的做法是用棧模擬括號序列匹配的過程,我們嘗試使用分塊,將元素個數減小至\(O(\sqrt n)\)級別。
對於每個塊,我們用棧來模擬暴力匹配的過程。如果兩個相鄰的左右括號出現適配,那麼我們稱這個塊是不合法的,那麼所有完全包含這個區間的詢問也就是不合法的。可以想象,對於一個合法的塊,它匹配剩下的一定是\(x\)個右括號和\(y\)個左括號。
那麼在查詢時,我們就能以一堆左/右括號為單位進行匹配了。令\(pre_{i,j}\)表示第\(i\)個塊的後\(j\)個右括號的絕對值的雜湊值,\(suf_{i,j}\)表示第\(i\)
由於需要進行結構體的賦值操作,可以使用指標代替vector或普通陣列做到\(O(1)\)賦值。具體實現可以看程式碼。
修改時就重構一下塊。
時間複雜度:\(O((n+q)\sqrt n)\)。
程式碼:
#include<bits/stdc++.h> using namespace std; #define re register int #define F(x,y,z) for(re x=y;x<=z;x++) #define FOR(x,y,z) for(re x=y;x>=z;x--) typedef long long ll; #define I inline void #define IN inline int #define C(x,y) memset(x,y,sizeof(x)) #define STS system("pause") template<class D>I read(D &res){ res=0;register D g=1;register char ch=getchar(); while(!isdigit(ch)){ if(ch=='-')g=-1; ch=getchar(); } while(isdigit(ch)){ res=(res<<3)+(res<<1)+(ch^48); ch=getchar(); } res*=g; } const int Mod=1e9+7,P=19260817,invp=494863259; int n,m,q,a[101000],sit,X,Y; int len,b[101000],S,ned[330],sn[330]; int p[101000],inv[101000]; int s[101000],R;vector<int>vec; IN Pow(int x,int y=Mod-2){ re res=1; while(y){ if(y&1)res=(ll)res*x%Mod; x=(ll)x*x%Mod; y>>=1; } return res; } IN Plus(int x,int y){(x+=y)>=Mod?x-=Mod:0;return x;} struct Hash{ int *has;int len; I init(int x){len=0;has=new int[x+1];has[0]=0;} I insert(int x){++len;has[len]=Plus((ll)has[len-1]*P%Mod,x);} IN calc(int x){if(x>len)return -1;return Plus(has[len],Mod-(ll)has[len-x]*p[x]%Mod);} I delet(int x){len-=x;} }pre[320],suf[320],tmp; stack<Hash>st; IN gethas(){ re res=0; for(auto d:vec)res=Plus((ll)res*P%Mod,d); return res; } I get(int x){ if(!ned[x])return; ned[x]=0; static int l,r;l=(x-1)*len+1;r=min(n,x*len); R=0;sn[x]=0; F(i,l,r){ if(a[i]>0||(a[i]<0&&(!R||s[R]<0))){s[++R]=a[i];continue;} if((a[i]+s[R]))return sn[x]=1,void(); R--; } vec.clear();while(R&&s[R]>0)vec.emplace_back(s[R]),R--;reverse(vec.begin(),vec.end()); suf[x].init(vec.size());for(auto w:vec)suf[x].insert(w); pre[x].init(R);while(R&&s[R]<0)pre[x].insert(-s[R]),R--; } IN ques(int x,int y){ if(!((y-x)&1))return 0; static int l,r;l=b[x];r=b[y]; if(r-l<2){ while(R)R--; F(i,x,y){ if(a[i]>0){s[++R]=a[i];continue;} if(!R||(a[i]+s[R]))return 0; R--; } if(!R)return 1; return 0; } F(i,l+1,r-1){ get(i); if(sn[i])return 0; } while(R)R--; F(i,x,min(n,len*l)){ if(a[i]>0){s[++R]=a[i];continue;} if(!R||(a[i]+s[R]))return 0; R--; } suf[0].init(R); vec.clear();while(R)vec.emplace_back(s[R]),R--;reverse(vec.begin(),vec.end()); for(auto w:vec)suf[0].insert(w); while(R)R--; F(i,(r-1)*len+1,y){ if(a[i]>0||(a[i]<0&&(!R||s[R]<0))){s[++R]=a[i];continue;} if((a[i]+s[R]))return 0; R--; } if(R&&s[R]>0)return 0; pre[0].init(R);while(R)pre[0].insert(-s[R]),R--; while(!st.empty())st.pop();st.emplace(suf[0]); F(i,l+1,r){ if(i<r)tmp=pre[i];else tmp=pre[0]; while(tmp.len&&!st.empty()){ if(st.top().len>=tmp.len){ if(st.top().calc(tmp.len)^tmp.calc(tmp.len))return 0; st.top().delet(tmp.len); if(!st.top().len)st.pop(); tmp.len=0; break; } if(st.top().calc(st.top().len)^tmp.calc(st.top().len))return 0; tmp.delet(st.top().len);st.pop(); } if(tmp.len)return 0; if(i==r){ while(!st.empty()&&!st.top().len)st.pop(); if(st.empty())return 1; return 0; } st.emplace(suf[i]); } return 0; } int main(){ read(n);read(m);p[0]=1;F(i,1,n)p[i]=(ll)p[i-1]*P%Mod;inv[0]=1;F(i,1,n)inv[i]=(ll)inv[i-1]*invp%Mod; F(i,1,n)read(a[i]); len=ceil(sqrt(n)+0.5);F(i,1,n)b[i]=((i-1)/len)+1;S=b[n]; F(i,1,S)ned[i]=1; read(q); while(q--){ read(sit);read(X);read(Y); if(sit==1)a[X]=Y,ned[b[X]]=1; else{ if(ques(X,Y))cout<<"Yes"<<endl; else cout<<"No"<<endl; } } return 0; } /* 10 10 10 4 2 -2 1 -1 -4 8 -8 -10 100 1 1 4 1 10 -4 2 6 9 1 3 4 1 4 -4 2 2 8 2 3 4 2 2 9 2 3 7 2 8 9 2 2 4 2 1 7 2 3 8 1 5 6 1 6 -6 2 5 6 1 8 5 1 9 -5 1 3 7 1 4 -7 1 8 10 1 9 -10 1 2 8 1 7 -8 2 3 4 2 4 6 2 1 3 1 8 1 1 9 -1 2 2 5 1 1 9 1 10 -9 1 5 4 1 6 -4 1 5 4 1 6 -4 2 2 7 2 8 9 2 2 7 2 2 7 1 2 3 1 7 -3 1 3 7 1 4 -7 2 1 10 */