zoukankan      html  css  js  c++  java
  • How Many Substrings?

    题意:求区间本质不同子串的个数

    题解:首先 询问离线 我们考虑加入一个字符时 只会影响这个节点到根路径上这些节点 我们考虑这些节点会产生的贡献是[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
    ",ans[i]);
        return 0;
    }
    

      

  • 相关阅读:
    《C++ Primer》笔记string,vector
    《C++ Primer》笔记创建动态数组new,delete
    《C++ Primer》笔记迭代器iterator
    浅析jQuery基础框架
    linux常用命令
    Javascript常用对象详细讲解
    Javascript兼容多种浏览器
    Vim常用命令
    提高 web 应用性能之 JavaScript 性能调优
    jQuery LigerUI使用教程入门篇
  • 原文地址:https://www.cnblogs.com/wang9897/p/9973106.html
Copyright © 2011-2022 走看看