• UVA


    维护一个01序列,一共四种操作:

    1.插入一个数

    2.删除一个数

    3.反转一个区间

    4.查询两个后缀的LCP

    用Splay或者Treap都可以做,维护哈希值,二分求LCP即可。

    注意反转序列的时候序列的哈希值也会改变,因此需要维护正反两个哈希值,在交换左右儿子的时候顺便交换两个哈希值即可。

    还有就是打标记的同时也要进行反转,不要等pushdown的时候再反转

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 typedef unsigned long long ll;
     4 const int N=4e5+10,M=1e9+7;
     5 int n,m,ch[N][2],siz[N],re[N],val[N],tot,rt;
     6 ll h1[N],h2[N],pm[N];
     7 char s[N];
     8 #define l(u) ch[u][0]
     9 #define r(u) ch[u][1]
    10 #define mid ((l+r)>>1)
    11 int newnode(int x) {int u=++tot; l(u)=r(u)=re[u]=0,siz[u]=1,val[u]=h1[u]=h2[u]=x; return u;}
    12 void pu(int u) {
    13     siz[u]=siz[l(u)]+siz[r(u)]+1;
    14     h1[u]=h1[l(u)]*pm[siz[r(u)]+1]+val[u]*pm[siz[r(u)]]+h1[r(u)];
    15     h2[u]=h2[r(u)]*pm[siz[l(u)]+1]+val[u]*pm[siz[l(u)]]+h2[l(u)];
    16 }
    17 void rv(int u) {swap(l(u),r(u)),swap(h1[u],h2[u]),re[u]^=1;}
    18 void pd(int u) {if(re[u])re[u]=0,rv(l(u)),rv(r(u));}
    19 void sp(int w,int k,int& u,int& v) {
    20     if(!w) {u=v=0; return;}
    21     pd(w);
    22     if(k>=siz[l(w)]+1)u=w,sp(r(w),k-(siz[l(w)]+1),r(u),v),pu(u);
    23     else v=w,sp(l(w),k,u,l(v)),pu(v);
    24 }
    25 void mg(int& w,int u,int v) {
    26     if(!u||!v) {w=u|v; return;}
    27     if(rand()%(siz[u]+siz[v])<siz[u])pd(u),w=u,mg(r(w),r(u),v);
    28     else pd(v),w=v,mg(l(w),u,l(v));
    29     pu(w);
    30 }
    31 void ins(int& u,int p,int x) {
    32     int L,R;
    33     sp(u,p,L,R),mg(L,L,newnode(x)),mg(u,L,R);
    34 }
    35 void del(int& u,int p) {
    36     int L,M,R;
    37     sp(u,p,L,R),sp(L,p-1,L,M),mg(u,L,R);
    38 }
    39 void rev(int& u,int l,int r) {
    40     int L,M,R;
    41     sp(u,r,L,R),sp(L,l-1,L,M);
    42     rv(M);
    43     mg(L,L,M),mg(u,L,R);
    44 }
    45 ll H(int& u,int l,int r) {
    46     int L,M,R;
    47     sp(u,r,L,R),sp(L,l-1,L,M);
    48     ll ret=h1[M];
    49     mg(L,L,M),mg(u,L,R);
    50     return ret;
    51 }
    52 int lcp(int& u,int L,int R) {
    53     int l=0,r=n-R+1,ret;
    54     while(l<=r) {
    55         if(H(u,L,L+mid-1)==H(u,R,R+mid-1))ret=mid,l=mid+1;
    56         else r=mid-1;
    57     }
    58     return ret;
    59 }
    60 void build(int& u,int l=1,int r=n) {
    61     if(l>r)return;
    62     u=newnode(s[mid-1]-'0'+1);
    63     build(l(u),l,mid-1),build(r(u),mid+1,r),pu(u);
    64 }
    65 int main() {
    66     srand(time(0));
    67     pm[0]=1;
    68     for(int i=1; i<N; ++i)pm[i]=pm[i-1]*M;
    69     while(scanf("%d%d",&n,&m)==2) {
    70         scanf("%s",s);
    71         tot=0,build(rt);
    72         while(m--) {
    73             int f,a,b;
    74             scanf("%d%d",&f,&a);
    75             if(f!=2)scanf("%d",&b);
    76             if(f==1)ins(rt,a,b+1),n++;
    77             else if(f==2)del(rt,a),n--;
    78             else if(f==3)rev(rt,a,b);
    79             else if(f==4)printf("%d
    ",lcp(rt,a,b));
    80         }
    81     }
    82     return 0;
    83 }
  • 相关阅读:
    .net framework 3.5 beta 2 / vs 2008 beta 2 有问题!
    提交了 VS 2008 sp1 对 Linq to SQL 的 xml 字段类型支持的一个 bug
    如何在 vista 的 iis 7 上面配置 asp.net 1.1 开发环境
    Linq to sql 中如何进行 left join
    Silverlight 2 beta 2 中目前不支持共享 WCF 的客户端类型
    Scott Guthrie 写的 Silverlight 教程索引
    利用 Xml Literal 功能复制一段 Xml
    Silverlight 2 beta 2 bug 解决办法 (持续更新中)
    C++使用内存映射文件入门
    如何在C++项目中引用Lib文件(VS2005)
  • 原文地址:https://www.cnblogs.com/asdfsag/p/11152586.html
Copyright © 2020-2023  润新知