• 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('
    ')); RI ptop=0;
    			while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('
    ');
    		}
    		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;
    }
    
  • 相关阅读:
    求X的N次乘方
    用辗转相除法求两个正整数的最大公约数
    求两、三个数中较大者的函数
    电文加密问题
    C#纯数学方法递归实现货币数字转换中文
    查找二维数组的查找之杨氏矩阵
    IT公司笔经面经
    排序2计数排序,桶排序
    windows Concurrency Runtimewindows的并行编程模型
    <c++ primer>第五部分 高级主题
  • 原文地址:https://www.cnblogs.com/cjjsb/p/10673200.html
Copyright © 2020-2023  润新知