• LOJ6041 「雅礼集训 2017 Day7」事情的相似度


    题目传送门

    分析:
    前缀的公共后缀,那直接SAM安排上
    两个前缀的公共后缀为两个串对应Parent树上节点的LCA
    于是([l,r])之间的公共后缀最长对应这些点两两在Parent树上LCA的最大的len

    Set启发式合并做法:
    建出了Parent树,我们考虑每一个点(u),合并它的子树集合时,两个集合中各取一个点的LCA一定是(u)
    我们可以找到若干对点ID相近且LCA为(u),他们会对答案造成贡献,而每次合并点集,产生的对数为较小的集合的大小
    使用启发式合并,空间复杂度是(O(nlogn)),时间复杂度(O(nlog^{2}n))
    点对预处理出来之后,可以离线+树状数组查询答案
    代码可以看yyb这篇博客,很好理解

    LCT+树状数组做法:
    我们将询问按(r)离线,每次按顺序加入一个点(i)时,我们将这个点到根的路径全部染成颜色(i),而某个点(u)原来的颜色(j)被覆盖,那么(u)就是(i,j)的LCA
    每个点的颜色都是最近被覆盖的,得到的点对与上面Set做法得到的点对是一样的
    到根路径染色实际上是LCT的access过程,于是直接用LCT维护,过程中即可更新树状数组求答案
    时间复杂度(O(nlog^{2}n))

    代码是第二种做法的:

    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<algorithm>
    #include<queue>
    #include<map>
    
    #define maxn 400005
    #define INF 0x3f3f3f3f
    
    using namespace std;
    
    inline int getint()
    {
    	int num=0,flag=1;char c;
    	while((c=getchar())<'0'||c>'9')if(c=='-')flag=-1;
    	while(c>='0'&&c<='9')num=num*10+c-48,c=getchar();
    	return num*flag;
    }
    
    int n,m;
    int Id[maxn];
    struct node{
    	int fa,nxt[2],len;
    }t[maxn];
    int lst,tot;
    int ch[maxn][2],val[maxn],tag[maxn],fa[maxn];
    vector<int>q[maxn];
    int p[maxn];
    int stk[maxn],tp;
    int mx[maxn],ans[maxn];
    char s[maxn];
    
    inline void insert(int c)
    {
    	int p=lst,np=lst=++tot;
    	t[np].len=t[p].len+1;
    	while(p&&!t[p].nxt[c])t[p].nxt[c]=np,p=t[p].fa;
    	if(!p)t[np].fa=1;
    	else
    	{
    		int q=t[p].nxt[c];
    		if(t[q].len==t[p].len+1)t[np].fa=q;
    		else
    		{
    			int nq=++tot;
    			memcpy(t[nq].nxt,t[q].nxt,sizeof t[q].nxt);
    			t[nq].len=t[p].len+1;
    			t[nq].fa=t[q].fa;
    			t[q].fa=t[np].fa=nq;
    			while(p&&t[p].nxt[c]==q)t[p].nxt[c]=nq,p=t[p].fa;
    		}
    	}
    }
    
    inline void update(int x,int num)
    {for(int i=n-x+1;i<=n;i+=i&(-i))mx[i]=max(mx[i],num);}
    inline int query(int x)
    {int num=0;for(int i=n-x+1;i;i-=i&(-i))num=max(num,mx[i]);return num;}
    inline bool isroot(int x)
    {return ch[fa[x]][0]!=x&&ch[fa[x]][1]!=x;}
    inline void change(int x,int num){val[x]=tag[x]=num;}
    inline void pushdown(int x)
    {
    	if(!tag[x])return;
    	if(ch[x][0])change(ch[x][0],tag[x]);
    	if(ch[x][1])change(ch[x][1],tag[x]);
    	tag[x]=0;
    }
    inline void rotate(int x)
    {
    	int y=fa[x],z=fa[y];
    	int l=(ch[y][1]==x),r=l^1;
    	if(!isroot(y))
    	{
    		if(ch[z][0]==y)ch[z][0]=x;else ch[z][1]=x;
    	}
    	fa[x]=z,fa[y]=x,ch[y][l]=ch[x][r],fa[ch[x][r]]=y,ch[x][r]=y;
    }
    inline void splay(int x)
    {
    	stk[++tp]=x;for(int i=x;!isroot(i);i=fa[i])stk[++tp]=fa[i];
    	while(tp)pushdown(stk[tp--]);
    	while(!isroot(x))
    	{
    		int y=fa[x],z=fa[y];
    		if(!isroot(y))
    		{
    			if((ch[z][0]==y)^(ch[y][0]==x))rotate(x);
    			else rotate(y);
    		}
    		rotate(x);
    	}
    }
    inline void access(int x,int num)
    {
    	int tmp=0;
    	for(;x;ch[x][1]=tmp,tmp=x,x=fa[x])
    		splay(x),update(val[x],t[x].len);
    	change(tmp,num);
    }
    
    int main()
    {
    	n=getint(),m=getint();
    	scanf("%s",s+1);
    	for(int i=1;i<=m;i++)p[i]=getint(),q[getint()].push_back(i);
    	lst=tot=1;
    	for(int i=1;i<=n;i++)insert(s[i]-'0'),Id[i]=lst;
    	for(int i=1;i<=tot;i++)fa[i]=t[i].fa;
    	for(int i=1;i<=n;i++)
    	{
    		access(Id[i],i);
    		int sz=q[i].size();
    		for(int j=0;j<sz;j++)ans[q[i][j]]=query(p[q[i][j]]);
    	}
    	for(int i=1;i<=m;i++)printf("%d
    ",ans[i]);
    }
    

  • 相关阅读:
    带妹入坑,她该怎样提高自己的编程能力?
    性能测试--cpu使用率过高怎么办
    loadrunner Controller 删除available scripts中无用脚本
    loadrunner 立即执行+定时执行设置
    loadrunner11 :脚本日志打印设置及举例说明
    loadrunner录制chrome脚本:页面无响应
    Error -27492: "HttpSendRequest" failed, Windows error code=12152 (invalid server response) and retry。。。
    loadrunner11错误:Error -27776: Server "wsg.cmszmail.ad" shut connection during attempt to negotiate SSL session [MsgId: MERR-27776]解决办法
    loadrunner11 错误:Error -26377: No match found for the requested parameter XXXX. web_custom_request(XXX) highest severity level was "ERROR",....... [MsgId: MMSG-26387]
    loadrunner11 执行bat批处理文件时获取bat文件所在路径 正确方式与采坑说明
  • 原文地址:https://www.cnblogs.com/Darknesses/p/13093735.html
Copyright © 2020-2023  润新知