CF1340F Nastya and CBS

题面

英文题面

题意:

题意

(n,k,q leq 10^5)

题解:考虑到暴力的做法是用栈模拟括号序列匹配的过程,我们尝试使用分块,将元素个数减小至(O(sqrt n))级别。

对于每个块,我们用栈来模拟暴力匹配的过程。如果两个相邻的左右括号出现适配,那么我们称这个块是不合法的,那么所有完全包含这个区间的询问也就是不合法的。可以想象,对于一个合法的块,它匹配剩下的一定是(x)个右括号和(y)个左括号。

那么在查询时,我们就能以一堆左/右括号为单位进行匹配了。令(pre_{i,j})表示第(i)个块的后(j)个右括号的绝对值的哈希值,(suf_{i,j})表示第(i)个块的前(j)个左括号的哈希值,然后用栈模拟匹配就行了。

由于需要进行结构体的赋值操作,可以使用指针代替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
*/
原文地址:https://www.cnblogs.com/Purple-wzy/p/13298809.html