标签:tor find set getch push 插入 产生 lct long
题意:求区间本质不同子串的个数
题解:首先 询问离线 我们考虑加入一个字符时 只会影响这个节点到根路径上这些节点 我们考虑这些节点会产生的贡献是[last-dis+1,last-dis[fa]] 因为要把区间尽可能放到右边 所以我们需要把这些节点的右端点平移到当前插入的位置 然后用线段树维护即可 考虑一个一个节点维护复杂度会退化 观察到修改这条路径的操作与LCT中access的操作类似 我们考虑在access的时候维护答案即可 复杂度nlgn
#include <algorithm> #include <iostream> #include <cstring> #include <cstdio> #include <vector> #include <stack> #include <queue> #include <cmath> #include <set> #include <map> #define mp make_pair #define pb push_back #define pii pair<int,int> #define link(x) for(edge *j=h[x];j;j=j->next) #define inc(i,l,r) for(int i=l;i<=r;i++) #define dec(i,r,l) for(int i=r;i>=l;i--) const int MAXN=3e5+10; const double eps=1e-8; #define ll long long using namespace std; struct edge{int t,v;edge*next;}e[MAXN<<1],*h[MAXN],*o=e; void add(int x,int y,int vul){o->t=y;o->v=vul;o->next=h[x];h[x]=o++;} ll read(){ ll x=0,f=1;char ch=getchar(); while(!isdigit(ch)){if(ch==‘-‘)f=-1;ch=getchar();} while(isdigit(ch))x=x*10+ch-‘0‘,ch=getchar(); return x*f; } int fa[MAXN],dis[MAXN],cnt,cur,ch[MAXN][26],n,m; int Ch[MAXN][2],maxx[MAXN],pre[MAXN],flag[MAXN],Last[MAXN],key[MAXN]; bool rt[MAXN]; ll tag[MAXN<<2],sum[MAXN<<2]; void push_up(int x,int l,int r){ if(!tag[x])return ; int mid=(l+r)>>1; tag[x<<1]+=tag[x];tag[x<<1|1]+=tag[x]; sum[x<<1]+=1ll*(mid-l+1)*tag[x]; sum[x<<1|1]+=1ll*(r-mid)*tag[x]; tag[x]=0; } void update(int x,int l,int r,int ql,int qr,int t){ if(ql<=l&&r<=qr){tag[x]+=t;sum[x]+=1ll*(r-l+1)*t;return ;} int mid=(l+r)>>1; push_up(x,l,r); if(ql<=mid)update(x<<1,l,mid,ql,qr,t); if(qr>mid)update(x<<1|1,mid+1,r,ql,qr,t); sum[x]=sum[x<<1]+sum[x<<1|1]; } ll ans1; void querty(int x,int l,int r,int ql,int qr){ if(ql<=l&&r<=qr){ans1+=sum[x];return ;} int mid=(l+r)>>1; push_up(x,l,r); if(ql<=mid)querty(x<<1,l,mid,ql,qr); if(qr>mid)querty(x<<1|1,mid+1,r,ql,qr); sum[x]=sum[x<<1|1]+sum[x<<1]; } void newnode(int x,int t){ Ch[x][0]=Ch[x][1]=0;maxx[x]=key[x]=t;pre[x]=0;flag[x]=0;Last[x]=0;rt[x]=1; } void reverse(int x,int t){ if(!x)return ; flag[x]=t;Last[x]=t; } void push(int x){ if(flag[x]){ reverse(Ch[x][0],flag[x]); reverse(Ch[x][1],flag[x]); flag[x]=0; } } void up(int x){maxx[x]=max(max(maxx[Ch[x][0]],maxx[Ch[x][1]]),key[x]);} void P(int x){ if(!rt[x])P(pre[x]); push(x); } void rotate(int x,int kind){ int y=pre[x]; pre[Ch[x][kind]]=y;Ch[y][!kind]=Ch[x][kind]; if(rt[y])rt[y]=0,rt[x]=1; else Ch[pre[y]][Ch[pre[y]][1]==y]=x; pre[x]=pre[y];Ch[x][kind]=y;pre[y]=x; up(y); } void splay(int x){ P(x); while(!rt[x]){ if(rt[pre[x]])rotate(x,Ch[pre[x]][0]==x); else{ int y=pre[x];int kind=Ch[pre[y]][0]==y; if(Ch[y][kind]==x)rotate(x,!kind),rotate(x,kind); else rotate(y,kind),rotate(x,kind); } } up(x); } int find_root(int x){ int t=x; while(Ch[t][0])t=Ch[t][0]; return fa[t]; } void calc(int x,int y,int l,int r){ if(x)update(1,1,n,x-r+1,x-l,-1); update(1,1,n,y-r+1,y-l,1); return ; } void access(int x,int t){ int y=0; while(x){ splay(x); if(Ch[x][1])rt[Ch[x][1]]=1,pre[Ch[x][1]]=x,Ch[x][1]=0; up(x); if(y)rt[y]=0; int root=find_root(x); if(x!=1){calc(Last[x],t,key[root],maxx[x]);} Ch[x][1]=y;up(x); y=x;x=pre[x]; } splay(1),reverse(1,t); } void Link(int x,int y){ splay(x);pre[x]=y; } void destory(int x){ splay(x);pre[Ch[x][0]]=pre[x];rt[Ch[x][0]]=1; Ch[x][0]=0;up(x); } void built(int x,int id){ int last=cur;cur=++cnt;dis[cur]=dis[last]+1;int p=last;newnode(cur,dis[cur]); for(;p&&!ch[p][x];p=fa[p])ch[p][x]=cur; if(!p)fa[cur]=1,Link(cur,1); else{ int q=ch[p][x]; if(dis[p]+1==dis[q])fa[cur]=q,Link(cur,q); else{ int nt=++cnt;dis[nt]=dis[p]+1;newnode(nt,dis[nt]); memcpy(ch[nt],ch[q],sizeof(ch[q])); destory(q);Link(nt,fa[q]); fa[nt]=fa[q];fa[q]=fa[cur]=nt; Link(q,nt);Link(cur,nt);Last[nt]=Last[q]; for(;ch[p][x]==q;p=fa[p])ch[p][x]=nt; } } } char str[MAXN]; ll ans[MAXN]; typedef struct node{ int l,id; }node; vector<node>vec[MAXN]; int main(){ n=read();m=read(); scanf("%s",str+1); int l,r; inc(i,1,m)l=read()+1,r=read()+1,vec[r].pb((node){l,i}); cnt=cur=1;newnode(1,0); inc(i,1,n){ built(str[i]-‘a‘,i); access(cur,i); for(int j=0;j<vec[i].size();j++)ans1=0,querty(1,1,n,vec[i][j].l,i),ans[vec[i][j].id]=ans1; } inc(i,1,m)printf("%lld\n",ans[i]); return 0; }
标签:tor find set getch push 插入 产生 lct long
原文地址:https://www.cnblogs.com/wang9897/p/9973106.html