• 一道题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
  • 相关阅读:
    HDU-2037 今年暑假不AC
    HDU-3348 coins
    CodeForces-985C Liebig's Barrels
    CSU-2034 Column Addition
    -----------------******Java API提供了几个常用包:
    DOM4j解析、修改、删除、增加、保存XML的方法
    Dom解析XML(添加,删除,修改,保存)
    ------------------------------------日期之间的转换
    -----------------------------------String类的常用方法
    ------------ 异常笔记
  • 原文地址:https://www.cnblogs.com/Blue233333/p/8777368.html
Copyright © 2020-2023  润新知