2024.2.26模拟赛T2题解

题目

对询问扫描线,建出 \(PAM\) 的失配树之后,每次查询相当于,把 \(r\) 对应节点到根路径染色之后,有多少个节点的值大于 \(l\),可以树剖+ODT 实现

code

#pragma GCC optimize("Ofast", "inline", "-ffast-math")
#pragma GCC target("avx,sse2,sse3,sse4,mmx")
#include<bits/stdc++.h>
using namespace std;
#define N 400005
#define pii pair<int,int> 
#define fir first
#define sec second
int n,m;
int pos[N];
char a[N];
vector<int> G[N];
namespace PAM{
	int tot,las;
	int len[N],f[N],ch[N][27];
	int nw(int l){
		len[++tot]=l,f[tot]=0;
		return tot;
	}
	void pre(){
		tot=-1,las=0,a[0]='#';
		nw(0),nw(-1),f[0]=1;
	}
	int gt_f(int p,int i){
		while(a[i-len[p]-1]!=a[i]) p=f[p];
		return p;
	}
	void ins(int c,int i){
		int p=gt_f(las,i);
		if(!ch[p][c]){
			int q=nw(len[p]+2);
			f[q]=ch[gt_f(f[p],i)][c];
			ch[p][c]=q;
		}
		las=ch[p][c],pos[i]=las;
	}
	void build(){
		for(int i=2;i<=tot;i++){
			if(!f[i]) f[i]=1;
			G[f[i]].push_back(i);
		}
	}
}
int tot;
int sz[N],son[N],tp[N],dfn[N],fu[N];
void dfs1(int x,int fa){
	sz[x]=1;
	for(auto y:G[x]){
		if(y==fa) continue;
		dfs1(y,x);sz[x]+=sz[y];
		if(sz[son[x]]<sz[y]) son[x]=y;
	}
}
struct A{
	int l,r,col;
};
bool operator < (A x,A y){
	if(x.l!=y.l) return x.l<y.l;
	return x.r<y.r;
}
set<A> q[N];
void dfs2(int x,int fa,int top){
	//printf("%d %d %d\n",x,fa,top);
	dfn[x]=++tot,tp[x]=top,fu[x]=fa;
	if(son[x]) dfs2(son[x],x,top);
	else q[top].insert({dfn[top],dfn[x],0});
	for(auto y:G[x]){
		if(y==fa||y==son[x]) continue;
		dfs2(y,x,y);
	}
}
int c[N];
inline int lowbit(int x){
	return x&(-x);
}
void add(int x,int y){
	if(!x) return ;
	for(;x;x-=lowbit(x)) c[x]+=y;
}
int sum(int x){
	int ans=0;
	for(;x<=n;x+=lowbit(x)) ans+=c[x];
	return ans;
}
void gai(int id,int x,int y){
	while(1){
		auto it=q[id].begin();
		A p=*it;
		if(p.r>=x){
			add(p.col,-(x-p.l+1));q[id].erase(it);
			if(p.r>x) q[id].insert({x+1,p.r,p.col});
			break;
		}
		add(p.col,-(p.r-p.l+1)),q[id].erase(it);
	}
	add(y,x-dfn[id]+1);
	q[id].insert({dfn[id],x,y});
}
void upd(int x,int y){
	while(x){
		gai(tp[x],dfn[x],y);
		x=fu[tp[x]];
	}
}
int ans[N];
vector<pii > qry[N];
inline int read(){
	int num=0;
	char c=getchar();
	while(c<'0'||c>'9') c=getchar();
	while('0'<=c&&c<='9') num=num*10+c-'0',c=getchar();
	return num;
}
int main(){
	freopen("necklace.in","r",stdin);
	freopen("necklace.out","w",stdout);
	scanf("%s",a+1);
	n=strlen(a+1);
	scanf("%d",&m);
	for(int i=1,x,y;i<=m;i++){
		x=read(),y=read();
		qry[y].push_back({x,i});
	}
	PAM::pre();
	for(int i=1;i<=n;i++) PAM::ins(a[i]-'a'+1,i);
	PAM::build();
	dfs1(1,0),dfs2(1,0,1);
	for(int i=1;i<=n;i++){
		upd(pos[i],i);
		for(auto p:qry[i]) ans[p.sec]=sum(p.fir)-1;
	}
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}

posted @ 2024-02-26 21:17  hubingshan  阅读(46)  评论(0)    收藏  举报