• bzoj3946


    题解:

    树套树

    treap+线段树

    treap就把线段树上的节点弄一下

    然后修改的时候

    把中间的一段一起加

    把两头重新计算(二分+hash)

    代码:

    #include<bits/stdc++.h>
    using namespace std;
    typedef unsigned int U;
    const int N=600005;
    int n,m,x,len,cur,st[N],en[N],q[N][3],stq[N];
    int pre[N],y[N],h[N],T[N],tag[N],enq[N];
    U po[N];
    char op[9],s[N],pool[N],str[N];
    namespace DS
    {
        const int N=15000005;
        int tot,l[N],r[N],v[N];
        U f[N];
        void up(int x)
         {
             v[x]=v[l[x]]+v[r[x]];
             f[x]=f[l[x]]*po[v[r[x]]]+f[r[x]];
         }
        int build(int a,int b,int c,int d)
         {
            int x=++tot;
            if (a==b)
             {
                 v[x]=1;
                 f[x]=str[a];
                 return x;
             }
            int mid=(a+b)/2;
            if (c<=mid)l[x]=build(a,mid,c,d);
            if (d>mid)r[x]=build(mid+1,b,c,d);
            up(x);
            return x; 
         } 
        int merge(int x,int y,int a,int b)
         {
             if (!x||!y)return x+y;
             int z=++tot,mid=(a+b)/2;
             l[z]=merge(l[x],l[y],a,mid);
             r[z]=merge(r[x],r[y],mid+1,b);
             up(z);
             return z;
         } 
        U hash(int x,int k)
         {
             int a=1,b=cur,mid,t;
             U h=0;
             while (a<b)
              {
                  mid=(a+b)/2;
                 t=v[l[x]];
                 if (k<=t)
                  {
                      b=mid;
                      x=l[x];
                 }
                else
                 {
                     h=h*po[t]+f[l[x]];
                     k-=t;
                     a=mid+1;
                     x=r[x];
                 } 
             }
            return h*po[v[x]]+f[x]; 
         } 
    }
    void ins(int x,int p)
    {
        pre[x]=DS::merge(pre[x],p,1,cur);
    }
    void down(int x)
    {
        if (pre[x])
         {
             ins(x<<1,pre[x]);
             ins(x<<1|1,pre[x]);
             pre[x]=0;
         }
    }
    void push(int x,int a,int b,int c,int d,int p)
    {
        if (c<=a&&b<=d)
         {
             ins(x,p);
             return;
         }
        down(x);
        int mid=(a+b)/2;
        if (c<=mid)push(x<<1,a,mid,c,d,p);
        if (d>mid)push(x<<1|1,mid+1,b,c,d,p);
    }
    void root(int x,int a,int b,int c)
    {
        if (a==b)
         {
             T[a]=DS::merge(T[a],pre[x],1,cur);
             pre[x]=0;
             return;
         }
        down(x);
        int mid=(a+b)/2;
        if (c<=mid)root(x<<1,a,mid,c);
        else root(x<<1|1,mid+1,b,c); 
    }
    int lcp(int x,int y)
    {
        root(1,1,n,x);
        root(1,1,n,y);
        x=T[x];y=T[y];
        int l=1,r=min(DS::v[x],DS::v[y]),t=0;
        while (l<=r)
         {
             int mid=(l+r)/2;
             if (DS::hash(x,mid)==DS::hash(y,mid))l=(t=mid)+1;
             else r=mid-1;
         }
        return t; 
    }
    void tag1(int x,int p)
    {
        h[x]+=p;
        tag[x]+=p;
    }
    void pb(int x)
    {
        if (tag[x])
         {
             tag1(x<<1,tag[x]);
             tag1(x<<1|1,tag[x]);
             tag[x]=0;
         }
    }
    void up(int x)
    {
        h[x]=min(h[x<<1],h[x<<1|1]);
    }
    void build(int x,int a,int b)
    {
        if (a==b)
         {
             h[x]=lcp(a,a+1);
             return;
         }
        int mid=(a+b)/2;
        build(x<<1,a,mid);
        build(x<<1|1,mid+1,b);
        up(x); 
    }
    void cal(int x,int a,int b,int c)
    {
        if (a==b)
         {
             h[x]=lcp(a,a+1);
             return;
         }
        pb(x); 
        int mid=(a+b)/2;
        if (c<=mid)cal(x<<1,a,mid,c);
        else cal(x<<1|1,mid+1,b,c); 
        up(x);
    }
    void change(int x,int a,int b,int c,int d,int p)
    {
        if (c<=a&&b<=d)
         {
             tag1(x,p);
             return;
         }
        pb(x);
        int mid=(a+b)/2;
        if (c<=mid)change(x<<1,a,mid,c,d,p);
        if (d>mid)change(x<<1|1,mid+1,b,c,d,p);
        up(x); 
    }
    int ask(int x,int a,int b,int c,int d)
    {
        if (c<=a&&b<=d)return h[x];
        pb(x);
        int mid=(a+b)/2,t=N;
        if (c<=mid)t=ask(x<<1,a,mid,c,d);
        if (d>mid)t=min(t,ask(x<<1|1,mid+1,b,c,d));
        return t;
    }
    void makepush(int l,int r,int A,int B)
    {
        push(1,1,n,l,r,DS::build(1,cur,A,B));
        if (l<r)change(1,1,n-1,l,r-1,B-A+1);
        if (l>1)cal(1,1,n-1,l-1);
        if (r<n)cal(1,1,n-1,r);
    }
    int query(int l,int r)
    {
        if (l==r)return lcp(l,l);
        return ask(1,1,n-1,l,r-1);
    }
    int main()
    {
        scanf("%d%d",&n,&m);
        for (int i=1;i<=n;i++)
         {
             scanf("%s",s);
             len=strlen(s);
             st[i]=cur+1;
             for (int j=0;j<len;j++)pool[++cur]=s[j];
             en[i]=cur;
         }
        for (int i=1;i<=m;i++)
         {
             scanf("%s%d%d",op,&q[i][1],&q[i][2]);
             if (op[0]=='Q')q[i][0]=1;
             else
              {
                  scanf("%s",s);
                  len=strlen(s);
                  stq[i]=cur+1;
                  for (int j=0;j<len;j++)pool[++cur]=s[j];
                  enq[i]=cur;
             }
         } 
        int cur=0;
        for (int i=m;i;i--)
         if (!q[i][0])
          {
              x=cur+1;
              for (int j=stq[i];j<=enq[i];j++)str[++cur]=pool[j];
              stq[i]=x;
              enq[i]=cur;
          } 
        for (int i=1;i<=n;i++)
         {
             x=cur+1;
             for (int j=st[i];j<=en[i];j++)str[++cur]=pool[j];
             st[i]=x;en[i]=cur;
         } 
        po[0]=1; 
        for (int i=1;i<=cur;i++)po[i]=po[i-1]*233;
        for (int i=1;i<=n;i++)T[i]=DS::build(1,cur,st[i],en[i]);
        build(1,1,n-1);
        for (int i=1;i<=m;i++)
         if (q[i][0])printf("%d
    ",query(q[i][1],q[i][2]));
         else makepush(q[i][1],q[i][2],stq[i],enq[i]); 
    }
  • 相关阅读:
    50 系统调用的实现
    49 进程调度预备开发(下)
    48 进程调度预备开发(上)
    47 多进程并行执行(下)
    IIC总线
    46 多进程并行执行(上)
    45 内核中的中断处理(下)
    解决错误/usr/bin/ld: cannot find -lz
    rsync只传输隐藏文件
    Firewall命令
  • 原文地址:https://www.cnblogs.com/xuanyiming/p/8458134.html
Copyright © 2020-2023  润新知