CF gym 100962D Deep Purple [suffix tree, the chain split tree, segment tree]

Codeforces

Thinking

I feel this good fairy ah off-line thinking qwq

For each interrogation \ ([l, r] \ ) is actually required \ (P_ {max} \) , so \ (LCS (S [. 1, P], S [. 1, R & lt])> PL \) , also is \ (LCS (S [. 1, P], S [. 1, R & lt]) + L> P \) .

First, press the interrogation offline \ (R & lt \) sort, then sweep from right to left, each

  1. It has been added to the list before the process of inquiry, to see whether the current position can be used as \ (the p-\) , and then ask to be deleted has been processed.
  2. The current inquiry into the go.

Playing out the suffix tree built, then the left side of the inequality is the \ ({dep_ LCA (P, R & lt)} L + \) .

The practice of violence is to enumerate \ (LCA \) , then check when dealing with inquiries of this position \ (l \) , plug ask when the \ (l \) to go into.

Split with chain accelerated tree: For each strand to \ (tag \) hit the deepest place. When asked on check processing \ (p \) to the root of the \ (\ max (dep_x + l ) \) and the \ (tag \) which inquiries from, and then delete it. Plug ask when he jumped all the way up, hit \ (Tag \) .

How the query? Sub-biggest \ (tag \) is discussed above or below, if it is directly above the check, otherwise check \ (\ max (l) \ ) plus the current \ (DEP \) .

Since each point can have a maximum of \ (tag \) in the tree line, so even with a \ (set \) record the point which tags.

(Probably speaks not very clear qwq)

Code

#include<bits/stdc++.h>
clock_t t=clock();
namespace my_std{
    using namespace std;
    #define pii pair<int,int>
    #define fir first
    #define sec second
    #define MP make_pair
    #define rep(i,x,y) for (int i=(x);i<=(y);i++)
    #define drep(i,x,y) for (int i=(x);i>=(y);i--)
    #define go(x) for (int i=head[x];i;i=edge[i].nxt)
    #define templ template<typename T>
    #define sz 402020
    typedef long long ll;
    typedef double db;
    mt19937 rng(chrono::steady_clock::now().time_since_epoch().count());
    templ inline T rnd(T l,T r) {return uniform_int_distribution<T>(l,r)(rng);}
    templ inline bool chkmax(T &x,T y){return x<y?x=y,1:0;}
    templ inline bool chkmin(T &x,T y){return x>y?x=y,1:0;}
    templ inline void read(T& t)
    {
        t=0;char f=0,ch=getchar();double d=0.1;
        while(ch>'9'||ch<'0') f|=(ch=='-'),ch=getchar();
        while(ch<='9'&&ch>='0') t=t*10+ch-48,ch=getchar();
        if(ch=='.'){ch=getchar();while(ch<='9'&&ch>='0') t+=d*(ch^48),d*=0.1,ch=getchar();}
        t=(f?-t:t);
    }
    template<typename T,typename... Args>inline void read(T& t,Args&... args){read(t); read(args...);}
    char __sr[1<<21],__z[20];int __C=-1,__zz=0;
    inline void Ot(){fwrite(__sr,1,__C+1,stdout),__C=-1;}
    inline void print(register int x)
    {
        if(__C>1<<20)Ot();if(x<0)__sr[++__C]='-',x=-x;
        while(__z[++__zz]=x%10+48,x/=10);
        while(__sr[++__C]=__z[__zz],--__zz);__sr[++__C]='\n';
    }
    void file()
    {
        #ifdef NTFOrz
        freopen("a.in","r",stdin);
        #endif
    }
    inline void chktime()
    {
        #ifndef ONLINE_JUDGE
        cout<<(clock()-t)/1000.0<<'\n';
        #endif
    }
    #ifdef mod
    ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x%mod) if (y&1) ret=ret*x%mod;return ret;}
    ll inv(ll x){return ksm(x,mod-2);}
    #else
    ll ksm(ll x,int y){ll ret=1;for (;y;y>>=1,x=x*x) if (y&1) ret=ret*x;return ret;}
    #endif
//  inline ll mul(ll a,ll b){ll d=(ll)(a*(double)b/mod+0.5);ll ret=a*b-d*mod;if (ret<0) ret+=mod;return ret;}
}
using namespace my_std;

int n,Q;
char s[sz];
int pos[sz];
struct hh{int l,r,id;const bool operator < (const hh &x) const {return r>x.r;}}q[sz];
int ans[sz];

int TT;
//struct SegmentTree
//{
    pii tr[sz<<2][2];
    #define ls k<<1
    #define rs k<<1|1
    #define lson ls,l,mid
    #define rson rs,mid+1,r
    void pushup(int k){tr[k][TT]=max(tr[ls][TT],tr[rs][TT]);}
    void modify(int k,int l,int r,int x,pii w)
    {
        if (l==r) return (void)(tr[k][TT]=w);
        int mid=(l+r)>>1;
        if (x<=mid) modify(lson,x,w);
        else modify(rson,x,w);
        pushup(k);
    }
    pii query(int k,int l,int r,int x,int y)
    {
        if (x<=l&&r<=y) return tr[k][TT];
        int mid=(l+r)>>1;pii ret=MP(-1e9,0);
        if (x<=mid) chkmax(ret,query(lson,x,y));
        if (y>mid) chkmax(ret,query(rson,x,y));
        return ret;
    }
//}T1,T2; 
// 1:维护一段里面最大的值是多少,以及它的位置。
// 2:维护一段里面加的l的最大值是多少,以及它的位置。 

namespace Tree
{
    struct hh{int t,nxt;}edge[sz];
    int head[sz],ecnt;
    void make_edge(int f,int t){edge[++ecnt]=(hh){t,head[f]};head[f]=ecnt;}
    int dfn[sz],top[sz],bot[sz],size[sz],son[sz],fa[sz],len[sz],T;
    #define v edge[i].t
    void dfs1(int x)
    {
        size[x]=1;
        go(x)
        {
            fa[v]=x;dfs1(v);
            size[x]+=size[v];
            if (size[v]>size[son[x]]) son[x]=v;
        }
    }
    void dfs2(int x,int tp)
    {
        dfn[x]=++T;
        top[x]=tp,bot[tp]=x;
        if (son[x]) dfs2(son[x],tp);
        go(x) if (v!=son[x]) dfs2(v,v);
    }
    #undef v
    set<pii>s[sz];
    // 维护这个地方打的标记有哪些 
    pii query(int x)
    {
        pii ret=MP(0,0);
        while (x)
        {
            TT=0;pii w1=::query(1,1,T,dfn[top[x]],dfn[x]);
            TT=1;pii w2=::query(1,1,T,dfn[x],dfn[bot[top[x]]]);
            w2.fir+=len[x];
            chkmax(ret,w1),chkmax(ret,w2);
            x=fa[top[x]];
        }
        return ret;
    }
    void modify(int x,int w,int id,bool add)
    {
        while (x)
        {
            if (add) s[x].insert(MP(w,id));
            else s[x].erase(MP(w,id));
            if (s[x].size())
            {
                auto cur=*s[x].rbegin();
                TT=1;::modify(1,1,T,dfn[x],cur);
                cur.fir+=len[x];
                TT=0;::modify(1,1,T,dfn[x],cur);
            }
            else TT=0,::modify(1,1,T,dfn[x],MP(0,0)),TT=1,::modify(1,1,T,dfn[x],MP(0,0));
            x=fa[top[x]];
        } 
    }
}

namespace SAM
{
    struct hh{int link,len,ch[28];}a[sz];
    int lst=1,cnt=1,root=1;
    int add(int c)
    {
        int cur=++cnt,p=lst;lst=cur;a[cur].len=a[p].len+1;
        while (p&&!a[p].ch[c]) a[p].ch[c]=cur,p=a[p].link;
        if (!p) return a[cur].link=1,cur;
        int q=a[p].ch[c];
        if (a[q].len==a[p].len+1) return a[cur].link=q,cur;
        int t=++cnt;a[t]=a[q];a[q].link=a[cur].link=t;a[t].len=a[p].len+1;
        while (p&&a[p].ch[c]==q) a[p].ch[c]=t,p=a[p].link;
        return cur;
    }
    void build(){rep(i,2,cnt) Tree::make_edge(a[i].link,i),Tree::len[i]=a[i].len;}
}

int main()
{
    file();
    read(n,Q);
    cin>>(s+1);
    rep(i,1,n) pos[i]=SAM::add(s[i]-'a'+1);
    SAM::build();
    Tree::dfs1(1),Tree::dfs2(1,1);
    rep(i,1,Q) read(q[i].l,q[i].r),q[i].id=i;
    sort(q+1,q+Q+1);
    int p=1;
    drep(i,n,1)
    {
        while (233)
        {
            pii w=Tree::query(pos[i]);int id=w.sec;
            if (w.fir<=i) break;
            ans[q[id].id]=i-q[id].l+1;
            Tree::modify(pos[q[id].r],q[id].l,id,0);
        }
        while (p<=Q&&q[p].r==i) Tree::modify(pos[q[p].r],q[p].l,p,1),++p;
    }
    rep(i,1,Q) printf("%d\n",ans[i]);
    return 0;
}

Guess you like

Origin www.cnblogs.com/p-b-p-b/p/11318629.html