LOJ #6041. 「雅礼集训 2017 Day7」事情的相似度

我可以大喊一声这就是个套路题吗?

首先看到LCP问题,那么套路的想到SAMSA的做法也有)

LCP的长度是它们在parent树上的LCA(众所周知),所以我们考虑同时统计多个点之间的LCA对

树上问题的话请出万能算法——LCT(这里准确的说应该是实链剖分),我们只需要不停地access就可以找到LCA了

然后怎么统计最后的答案,区间询问用莫队?这里的两个信息(最大值,边的虚实)显然都不能撤销

我们直接大力离线,从左往右把点一个个扔到LCT上,然后对于每个点开一个树状数组维护后缀最大值,由于这里只有加入操作显然是合法的

那么问题就变成怎么维护树状数组了,这个也很套路,在LCT上打懒标记splay的时候下传即可

CODE

#include<cstdio>
#include<cctype>
#include<vector>
#define RI register int
#define CI const int&
#define Tp template <typename T>
using namespace std;
const int N=100005;
int n,m,x,len[N<<1],anc[N<<1],id[N],ans[N],L[N],tot; vector <int> v[N];
class FileInputOutput
{
    private:
        static const int S=1<<21;
        #define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
        #define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
        char Fin[S],Fout[S],*A,*B; int Ftop,pt[15];
    public:
        Tp inline void read(T& x)
        {
            x=0; char ch; while (!isdigit(ch=tc()));
            while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
        }
        inline void get_digit(int& x)
        {
            char ch; while (!isdigit(ch=tc())); x=ch&15;
        }
        Tp inline void write(T x)
        {
            if (!x) return (void)(pc('0'),pc('\n')); RI ptop=0;
            while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('\n');
        }
        inline void Fend(void)
        {
            fwrite(Fout,1,Ftop,stdout);
        }
        #undef tc
        #undef pc
}F;
class Suffix_Automation
{
    private:
        int ch[N<<1][2],lst;
    public:
        inline Suffix_Automation() { lst=tot=1; }
        inline void expand(CI c,CI pos)
        {
            int now=++tot,fa=lst; id[pos]=lst=now; len[now]=len[fa]+1;
            while (fa&&!ch[fa][c]) ch[fa][c]=now,fa=anc[fa];
            if (!fa) return (void)(anc[now]=1); int x=ch[fa][c];
            if (len[fa]+1==len[x]) return (void)(anc[now]=x);
            int y=++tot; ch[y][0]=ch[x][0]; ch[y][1]=ch[x][1];
            anc[y]=anc[x]; len[y]=len[fa]+1; anc[now]=anc[x]=y;
            while (fa&&ch[fa][c]==x) ch[fa][c]=y,fa=anc[fa];
        }
}SAM;
class Tree_Array
{
    private:
        int mx[N];
        inline void maxer(int& x,CI y)
        {
            if (y>x) x=y;
        }
    public:
        #define lowbit(x) x&-x
        inline void add(RI x,CI y)
        {
            for (;x;x-=lowbit(x)) maxer(mx[x],y);
        }
        inline int get(RI x,int ret=0)
        {
            for (;x<=n;x+=lowbit(x)) maxer(ret,mx[x]); return ret;
        }
        #undef lowbit
}BIT;
class Link_Cut_Tree
{
    private:
        struct splay
        {
            int ch[2],fa,val,tag;
        }node[N<<1]; int stack[N<<1],top;
        #define lc(x) node[x].ch[0]
        #define rc(x) node[x].ch[1]
        #define fa(x) node[x].fa
        #define V(x) node[x].val
        #define T(x) node[x].tag
        inline void pushdown(CI now)
        {
            if (T(now)) T(lc(now))=V(lc(now))=T(rc(now))=V(rc(now))=T(now),T(now)=0;
        }
        inline int identify(CI now)
        {
            return rc(fa(now))==now;
        }
        inline void connect(CI x,CI y,CI d)
        {
            node[fa(x)=y].ch[d]=x;
        }
        inline bool isroot(CI now)
        {
            return lc(fa(now))!=now&&rc(fa(now))!=now;
        }
        inline void rotate(CI now)
        {
            int x=fa(now),y=fa(x),d=identify(now);
            if (!isroot(x)) node[y].ch[identify(x)]=now; fa(now)=y;
            connect(node[now].ch[d^1],x,d); connect(x,now,d^1);
        }
        inline void splay(int now)
        {
            int t=now; while (stack[++top]=t,!isroot(t)) t=fa(t);
            while (top) pushdown(stack[top--]); for (;!isroot(now);rotate(now))
            t=fa(now),!isroot(t)&&(rotate(identify(now)!=identify(t)?now:t),0);
        }
    public:
        inline void init(void)
        {
            for (RI i=1;i<=tot;++i) fa(i)=anc[i];
        }
        inline void access(int x,CI pos,int y=0)
        {
            for (;x;x=fa(y=x)) splay(x),BIT.add(V(x),len[x]),rc(x)=y; T(y)=V(y)=pos;
        }
        #undef lc
        #undef rc
        #undef fa
        #undef V
        #undef T
}LCT;
int main()
{
    //freopen("A.in","r",stdin); freopen("A.out","w",stdout);
    RI i; for (F.read(n),F.read(m),i=1;i<=n;++i)
    F.get_digit(x),SAM.expand(x,i); for (i=1;i<=m;++i)
    F.read(L[i]),F.read(x),v[x].push_back(i);
    for (LCT.init(),i=1;i<=n;++i)
    {
        LCT.access(id[i],i); for (int it:v[i]) ans[it]=BIT.get(L[it]);
    }
    for (i=1;i<=m;++i) F.write(ans[i]); return F.Fend(),0;
}
posted @ 2019-04-08 20:35 hl666 阅读(...) 评论(...) 编辑 收藏