一道题13

$n leq 100000$的01串(其实啥串都行),给$m leq 100000$个询问,每次问$[L,R]$,回答:前缀$L,L+1,...,R$中,任意两个的最长公共后缀的长度。

这种前缀后缀的询问,无脑先建个后缀树先,反串的后缀树正串的sam哦。

然后现在问题就是:每次问一个区间的点集,问他们俩俩LCA的权值最大的一个。

可以发现一个点对答案有贡献的时候,他子树里至少选了两个点。如果询问按右端点从小到大排序,从小到大动态把点加进去,那我只要知道倒数第二次覆盖他的是谁即可。为啥呢?首先谁覆盖他他对答案贡献一样嘛因为一个点代表的串的长度是不会变的,然后右端点固定的时候我肯定希望那个上次覆盖他的点尽量大,这样就能贡献给更多的区间,您比如说这倒数第二次覆盖他的是x,倒数第三次是y,那由于我从小到大加的所以x>y,然后x能贡献的区间[L,R],y可能贡献不到,在y<L<x时发生这种情况。

慢着还有个问题这个覆盖复杂度不大对?一直往上跳的操作不是LCT咩?

  1 #include<stdio.h>
  2 #include<string.h>
  3 #include<stdlib.h>
  4 //#include<math.h>
  5 //#include<queue>
  6 #include<algorithm>
  7 //#include<iostream>
  8 //#include<assert.h>
  9 using namespace std;
 10 
 11 int n,m;
 12 #define maxn 200011
 13 
 14 struct BIT
 15 {
 16     int a[maxn],n;
 17     void clear(int m) {n=m;}
 18     void add(int x,int v) {if (x<1 || x>n) return; x=n-x+1; for (;x<=n;x+=x&-x) a[x]=max(a[x],v);}
 19     int query(int x)
 20     {
 21         int now=0,tot=0;
 22         for (int i=18;i>=0;i--)
 23         {
 24             now+=(1<<i);
 25             if (now<=n && max(tot,a[now])<x) tot=max(tot,a[now]);
 26             else now-=(1<<i);
 27         }
 28         return n-(now+1)+1;
 29     }
 30 }bit;
 31 //xia biao chuan jin bit shi ji de fan guo lai
 32 
 33 struct SAM
 34 {
 35     struct Node
 36     {
 37         int ch[2],pos,pre;
 38     }a[maxn<<1];
 39     int size,last,num[maxn];
 40     SAM() {size=0; last=0; a[0].pre=-1; a[0].pos=0;}
 41     
 42     void insert(int id,int p)
 43     {
 44         int x=++size,y=last; last=x; num[p]=x+1;
 45         a[x].pos=p; a[x].ch[0]=a[x].ch[1]=0;
 46         for (;~y && !a[y].ch[id];y=a[y].pre) a[y].ch[id]=x;
 47         if (!~y) a[x].pre=0;
 48         else if (a[a[y].ch[id]].pos==a[y].pos+1) a[x].pre=a[y].ch[id];
 49         else
 50         {
 51             int z=a[y].ch[id],w=++size; a[w]=a[z]; a[w].pos=a[y].pos+1;
 52             a[z].pre=a[x].pre=w;
 53             for (;~y && a[y].ch[id]==z;y=a[y].pre) a[y].ch[id]=w;
 54         }
 55     }
 56 }sam;
 57 
 58 struct LCT
 59 {
 60     struct Node
 61     {
 62         int son[2],fa;
 63         int tag,Max,v;
 64     }a[maxn<<1];
 65     int n;
 66     void clear(int m) {n=m;}
 67     void up(int x) {if (!x) return; Node &b=a[x]; b.Max=max(b.v,max(a[b.son[0]].Max,a[b.son[1]].Max));}
 68     void down(int x) {Node &b=a[x]; a[b.son[0]].tag=b.tag; a[b.son[1]].tag=b.tag;}
 69     bool isroot(int x) {Node &b=a[x]; return !b.fa || (a[b.fa].son[0]!=x && a[b.fa].son[1]!=x);}
 70     int sta[maxn],top;
 71     void download(int x)
 72     {
 73         top=0; sta[++top]=x; for (int i=x;!isroot(i);i=a[i].fa) sta[++top]=a[i].fa;
 74         while (top) down(sta[top--]);
 75     }
 76     void rotate(int x)
 77     {
 78         int y=a[x].fa,z=a[y].fa;
 79         bool w=(x==a[y].son[0]);
 80         a[x].fa=z; if (!isroot(y)) a[z].son[y==a[z].son[1]]=x;
 81         a[y].son[w^1]=a[x].son[w]; if (a[x].son[w]) a[a[x].son[w]].fa=y;
 82         a[x].son[w]=y; a[y].fa=x;
 83         up(y); up(z);
 84     }
 85     void splay(int x)
 86     {
 87         if (!x) return;
 88         download(x);
 89         while (!isroot(x))
 90         {
 91             int y=a[x].fa,z=a[y].fa;
 92             if (!isroot(y)) {if ((x==a[y].son[0])^(y==a[z].son[0])) rotate(x); else rotate(y);} rotate(x);
 93         }
 94         up(x);
 95     }
 96     void access(int x,int col)
 97     {
 98         int y=0; while (x)
 99         {
100             splay(x); a[x].son[1]=0; up(x);
101             bit.add(a[x].Max,a[x].tag);
102             a[x].son[1]=y; up(x);
103             y=x; x=a[x].fa;
104         }
105         a[y].tag=col;
106     }
107 }t;
108 
109 void buildtree()
110 {for (int i=1;i<=sam.size;i++) t.a[i+1].fa=sam.a[i].pre+1,t.a[i+1].v=t.a[i+1].Max=sam.a[i].pos;}
111 
112 struct Ques{int id,l,next;}ques[maxn<<1]; int fques[maxn],lq=2;
113 void in(int x,int L,int id) {Ques &e=ques[lq]; e.id=id; e.l=L; e.next=fques[x]; fques[x]=lq++;}
114 
115 char s[maxn]; int ans[maxn];
116 int main()
117 {
118     scanf("%d%d",&n,&m);
119     scanf("%s",s+1);
120     for (int i=1;i<=n;i++) sam.insert(s[i]-'0',i);
121     t.clear(sam.size+1); buildtree();
122     
123     for (int i=1,L,R;i<=m;i++) scanf("%d%d",&L,&R),in(R,L,i);
124     bit.clear(n);
125     for (int i=1;i<=n;i++)
126     {
127         t.access(sam.num[i],i);
128         for (int j=fques[i];j;j=ques[j].next)
129         {
130             Ques &e=ques[j];
131             ans[e.id]=bit.query(e.l);
132         }
133     }
134     
135     for (int i=1;i<=m;i++) printf("%d
",ans[i]);
136     return 0;
137 }
View Code
原文地址:https://www.cnblogs.com/Blue233333/p/8777368.html