【LOJ6041】「雅礼集训 2017 Day7」事情的相似度(用LCT维护SAM的parent树)
大致题意: 给你一个\(01\)串,每次询问前缀编号在一段区间内的两个前缀的最长公共后缀的长度。
离线存储询问
考虑将询问离线,按右端点大小用邻接表存下来(直接排序当然也可以啦)。
这样的好处是什么呢?
我们就可以对于每一个枚举到的右端点来对答案进行更新,然后再处理对应询问。
则对于当前一个已确定的右端点\(r\),显然询问\([l,r]\)的答案就是两个编号均大于等于\(l\)的点的答案的最大值(注意无须考虑右边界),而这可以直接拿线段树或树状数组统计。
由此可以发现,这样一来最大的好处就在于,不需要删除某种情况下的答案,而是可以直接叠加统计。
这样一来就可做了许多。
后缀自动机:题意转化
首先,这道题看起来很像\(SAM\)。
所以,我们先无脑打个板子,建一个后缀自动机。
然后来考虑一下性质。
首先我们要知道,对于两个前缀,它们的最长公共后缀长度,就相当于在\(parent\)树上这两个点的\(LCA\)的\(Len\)。
那么,问题似乎就转换成了求\(parent\)树上一个点集内任意两点的\(LCA\)的\(Len\)的最大值。
然后就可以大力数据结构硬搞了。
\(LCT\)维护\(parent\)树
考虑之前提到过的离线,则我们只需考虑每次加入一个新的节点对答案造成的影响。
结合题意转化,则其实也就相当于要求新加入的这个点与之前所有点的\(LCA\)的\(Len\)。
注意\(LCA\),便可以想到\(LCT\)中的一个技巧:\(Access\)求\(LCA\)。(关于这个技巧,有一道挺好的例题:【BZOJ4573】[ZJOI2016] 大森林)
因此,修改只要在\(Access\)的过程中进行即可。
然后考虑如果一个点被作为新加入点与之前多个点的\(LCA\),则显然应该选择较后出现的进行单点修改(因为询问时我们区间询问某个位置到当前右端点间的最大值,则显然较后出现的可以影响到较先出现的答案)。
则我们可以记录一个\(V\),每次\(Access\)后把根所在的\(Splay\)内所有节点(即树中\(LCA(now,pre)\)到根节点的路径上的所有节点)的\(V\)改为新加入节点的编号。
具体实现详见代码。
代码
#include<bits/stdc++.h>
#define Tp template<typename Ty>
#define Ts template<typename Ty,typename... Ar>
#define Reg register
#define RI Reg int
#define Con const
#define CI Con int&
#define I inline
#define W while
#define N 100000
#define Gmax(x,y) (x<(y)&&(x=(y)))
#define swap(x,y) (x^=y^=x^=y)
#define pb(x,y) (nxt[y]=lnk[x],lnk[x]=y)
using namespace std;
int n,m,a[N+5],q[N+5],lnk[N+5],nxt[N+5],ans[N+5];
class FastIO
{
private:
#define FS 100000
#define tc() (A==B&&(B=(A=FI)+fread(FI,1,FS,stdin),A==B)?EOF:*A++)
#define pc(c) (C^FS?FO[C++]=c:(fwrite(FO,1,C,stdout),FO[(C=0)++]=c))
#define tn (x<<3)+(x<<1)
#define D isdigit(c=tc())
int T,C;char c,*A,*B,FI[FS],FO[FS],S[FS];
public:
I FastIO() {A=B=FI;}
Tp I void read(Ty& x) {x=0;W(!D);W(x=tn+(c&15),D);}
Tp I void write(Ty x) {W(S[++T]=x%10+48,x/=10);W(T) pc(S[T--]);}
Ts I void read(Ty& x,Ar&... y) {read(x),read(y...);}
Tp I void writeln(Con Ty& x) {write(x),pc('\n');}
I void readbit(int& x) {W(!D);x=c&1;}
I void clear() {fwrite(FO,1,C,stdout),C=0;}
}F;
template<int SZ> class SuffixAutomation//后缀自动机
{
private:
int lst;struct Trie {int L,F,S[2];}O[SZ<<1];
public:
int tot,l[SZ<<1],f[SZ<<1];I SuffixAutomation() {tot=lst=1;}
I void Record() {for(RI i=1;i<=tot;++i) l[i]=O[i].L,f[i]=O[i].F;}
I int Insert(CI x)//插入节点
{
RI p=lst,q,k,now=lst=++tot;O[now].L=O[p].L+1;
W(p&&!O[p].S[x]) O[p].S[x]=now,p=O[p].F;if(!p) return O[now].F=1,now;
if(O[p].L+1==O[q=O[p].S[x]].L) return O[now].F=q,now;
O[k=++tot]=O[q],O[k].L=O[p].L+1,O[now].F=O[q].F=k;
W(p&&!(O[p].S[x]^q)) O[p].S[x]=k,p=O[p].F;return now;
}
};
template<int SZ> class TreeArray//树状数组
{
private:
#define lowbit(x) ((x)&-(x))
int a[SZ+5];
public:
I void Add(RI x,CI v) {W(x) Gmax(a[x],v),x-=lowbit(x);}//单点修改
I int Qry(RI x) {RI t=0;W(x<=n) Gmax(t,a[x]),x+=lowbit(x);return t;}//区间询问
};
class LinkCutTree//LCT
{
private:
#define Upt(x,v) (O[x].f=O[x].V=v)
#define PD(x) (O[x].f&&(Upt(O[x].S[0],O[x].f),Upt(O[x].S[1],O[x].f),O[x].f=0))
#define IR(x) (O[O[x].F].S[0]^x&&O[O[x].F].S[1]^x)
#define Wh(x) (O[O[x].F].S[1]==x)
#define Co(x,y,d) (O[O[x].F=y].S[d]=x)
static Con int SZ=N<<1;int p[SZ+5],St[SZ+5];struct node {int f,V,F,S[2];}O[SZ+5];
SuffixAutomation<N> SAM;TreeArray<N<<1> T;
I void Ro(CI x)
{
RI f=O[x].F,p=O[f].F,d=Wh(x);!IR(f)&&(O[p].S[Wh(f)]=x);
O[x].F=p,Co(O[x].S[d^1],f,d),Co(f,x,d^1);
}
I void S(CI x)
{
RI f=x,T=0;W(St[++T]=f,!IR(f)) f=O[f].F;W(T) PD(St[T]),--T;
W(!IR(x)) f=O[x].F,!IR(f)&&(Ro(Wh(x)^Wh(f)?x:f),0),Ro(x);
}
public:
I void Init(CI x,int* v)
{
RI i;for(i=1;i<=n;++i) p[i]=SAM.Insert(v[i]);SAM.Record();
for(i=1;i<=SAM.tot;++i) O[i].F=SAM.f[i];
}
I void Ac(RI x,CI v)//Access求LCA的过程,注意更新节点信息与答案
{
RI s;for(x=p[x],s=0;x;x=O[s=x].F) S(x),
T.Add(O[x].V,SAM.l[x]),O[x].S[1]=s;Upt(s,v);
}
I int Query(CI x) {return T.Qry(x);}//询问答案
}LCT;
int main()
{
RI Qtot,i,j,x;for(F.read(n,Qtot),i=1;i<=n;++i) F.readbit(a[i]);
for(LCT.Init(n,a),i=1;i<=Qtot;++i) F.read(q[i],x),pb(x,i);//离线用邻接表存储
for(i=1;i<=n;++i) for(LCT.Ac(i,i),j=lnk[i];j;j=nxt[j]) ans[j]=LCT.Query(q[j]);//枚举右端点,更新信息并处理询问
for(i=1;i<=Qtot;++i) F.writeln(ans[i]);return F.clear(),0;//输出答案
}
【LOJ6041】「雅礼集训 2017 Day7」事情的相似度(用LCT维护SAM的parent树)的更多相关文章
- LOJ6041. 「雅礼集训 2017 Day7」事情的相似度 [后缀树,LCT]
LOJ 思路 建出反串的后缀树,发现询问就是问一个区间的点的\(lca\)的深度最大值. 一种做法是dfs的时候从下往上合并\(endpos\)集合,发现插入一个点的时候只需要把与前驱后继的贡献算进去 ...
- 「雅礼集训 2017 Day7」事情的相似度
「雅礼集训 2017 Day7」事情的相似度 题目链接 我们先将字符串建后缀自动机.然后对于两个前缀\([1,i]\),\([1,j]\),他们的最长公共后缀长度就是他们在\(fail\)树上对应节点 ...
- 【LOJ 6041】「雅礼集训 2017 Day7」事情的相似度
Description 人的一生不仅要靠自我奋斗,还要考虑到历史的行程. 历史的行程可以抽象成一个 01 串,作为一个年纪比较大的人,你希望从历史的行程中获得一些姿势. 你发现在历史的不同时刻,不断的 ...
- 【刷题】LOJ 6041 「雅礼集训 2017 Day7」事情的相似度
题目描述 人的一生不仅要靠自我奋斗,还要考虑到历史的行程. 历史的行程可以抽象成一个 01 串,作为一个年纪比较大的人,你希望从历史的行程中获得一些姿势. 你发现在历史的不同时刻,不断的有相同的事情发 ...
- 【loj6041】「雅礼集训 2017 Day7」事情的相似度 后缀自动机+STL-set+启发式合并+离线+扫描线+树状数组
题目描述 给你一个长度为 $n$ 的01串,$m$ 次询问,每次询问给出 $l$ .$r$ ,求从 $[l,r]$ 中选出两个不同的前缀的最长公共后缀长度的最大值. $n,m\le 10^5$ 题解 ...
- LOJ #6041. 「雅礼集训 2017 Day7」事情的相似度
我可以大喊一声这就是个套路题吗? 首先看到LCP问题,那么套路的想到SAM(SA的做法也有) LCP的长度是它们在parent树上的LCA(众所周知),所以我们考虑同时统计多个点之间的LCA对 树上问 ...
- loj#6041. 「雅礼集训 2017 Day7」事情的相似度(SAM set启发式合并 二维数点)
题意 题目链接 Sol 只会后缀数组+暴躁莫队套set\(n \sqrt{n} \log n\)但绝对跑不过去. 正解是SAM + set启发式合并 + 二维数点/ SAM + LCT 但是我只会第一 ...
- loj#6041. 「雅礼集训 2017 Day7」事情的相似度(后缀自动机+启发式合并)
题面 传送门 题解 为什么成天有人想搞些大新闻 这里写的是\(yyb\)巨巨说的启发式合并的做法(虽然\(LCT\)的做法不知道比它快到哪里去了--) 建出\(SAM\),那么两个前缀的最长公共后缀就 ...
- LOJ #6041. 「雅礼集训 2017 Day7」事情的相似度 LCT+SAM+线段树
Code: #include<bits/stdc++.h> #define maxn 200003 using namespace std; void setIO(string s) { ...
随机推荐
- 打ms15-034补丁出现“此更新 不适用于您的计算机”
1.MS15-034漏洞的补丁是KB3042553; 2.如果在一台Windows Server 2012 R2的服务器上直接安装补丁文件KB3042553,可能会出现“此更新 不适用于您的计算机”的 ...
- 【Tensorflow】 Object_detection之配置Training Pipeline
参考:Configuring an object detection pipeline 1.config文件 配置好的config文件存放路径:object_detection/samples/con ...
- (转)通过shell脚本实现批量添加用户和设置随机密码以及生产环境如何批量添加
通过shell脚本实现批量添加用户和设置随机密码以及生产环境如何批量添加 原文:http://www.21yunwei.com/archives/4773 有一个朋友问我如何批量创建用户和设置密码 , ...
- Spark 1.6.2 + Beam 2.0.0读取Mongodb数据进行相应逻辑处理
不多说,直接上干货! http://blog.csdn.net/jianglushou9763/article/details/73332805 如果需要 APACHE BEAM2.0.0版本如何支持 ...
- spring依赖版本约束
<dependencyManagement> <dependencies> <dependency> <groupId>org.springframew ...
- Unity中Shader和AssetBundle结合使用的注意事项
之前遇到了一件事情就是打包安卓的ab后,unity在editor启动下,加载出来的abshader丢失,其实发布安卓后运行是正常的,当时还纠结了半天,还写了个重新赋值的脚本 下面是unity开发的一些 ...
- jqGrid 将行的字变成超连接
今天在项目中碰到要将jqGrid中的行做成超连接,请看代码步骤: name: , align: "left", formatter: function (cellValue, op ...
- java File delete()执行失败原因(转)
java.io.File里的delete操作很实用也很常用,可以用来删除单独的文件和某一目录.但有时候会出现delete失败的情况,出现这种情况的原因一般有以下几种:1.删除时还有其他程序在使用该文件 ...
- 一个简单问题引发对IEnumerable和IQueryable的思考
问题概述: 首先看下图,有客户表和客户负责人表关系是多对多,访问数据库使用的是EF所以这里我们开启了延迟加载,需求就是将每个客户的所有负责人逗号拼接显示在负责人这一栏位, 对你没看错需求就是这么 ...
- Scanners-Box:开源扫描器大全 2017-04-22
Scanners-Box:开源扫描器大全 2017-04-22 Scanners-Box是一个集合github平台上的安全行业从业人员自研开源扫描器的仓库,包括子域名枚举.数据库漏洞扫描.弱口令或信息 ...