• Jewel Magic UVA


    Jewel Magic UVA - 11996

    这是一道用splay/非旋treap做的题(这里用的是非旋treap)

    1/2/3是splay/非旋treap的常规操作。对于操作4,可以用哈希法求LCP。记hash(i,L)为子串[i,i+L-1](即第i个开始的L个)的hash值。记s[i]为序列第i位(编号从1开始),n为序列长度

    如果通过某种方式做到能在O(logn)时间内取出一段子串的hash值,那么二分答案(即LCP长度x),可以在O(logn)时间内判一个x是否合法(如果hash(l,x)==hash(r,x)则认为[l,l+x-1]和[r,r+x-1]是相同的,合法,否则不合法),可以做到在O(log^2n)内完成一个操作4。当然,hash判字符串是否相同正确性可能受影响,因此可以多计算一些hash,当他们都相同时才认为字符串相同,可以将错误率降到足够小。

    如何维护一段子串的hash值?首先定义x为任意整数,定义$hash(i,L)=s[i+L-1]*x^{L-1}+s[i+L-2]*x^{L-2}+...+s[i+1]*x+s[i]$

    (这里及之后都省略了取模)

    (简单记法:左边乘的次数小)

    (另一种记法:另一种求法的伪代码表示:ans=0;for(j=i+L-1;j>=i;j--)  ans=ans*x+s[j];)

    可以发现:如果已知hash(i,p)和hash(i+p,q)(即已知[i,i+p-1]和[i+p,i+p+q-1]的hash值),要求hash(i,p+q)(就是这两段合起来的hash值),那么:

    令j=i+p,那么$hash(i,p+q)$

    $=s[j+q-1]*x^{p+q-1}+s[j+q-2]*x^{p+q-2}+...+s[j]*x^p+s[i+p-1]*x^{p-1}+...+s[i]*x^0$

    所以$hash(i,p+q)=hash(j,q)*x^p+hash(i,p)=hash(i,p)+hash(i+p,q)*x^p$

    这样就得到了对于平衡树某个节点,根据子节点为根的子树的hash值与自身值求以自身为根的子树的hash值的方法(先将左子树和自身合起来,再将结果与右子树合起来)

    当然,由于此题有一个翻转操作,对于一个节点要维护两个hash:正向序列hash和反向序列hash。翻转操作时顺便交换一下两个的值。

    附:这道题没有卡hash,单hash就能过,

    附:听说操作4有O(logn)的方法?待解决

    错误记录:

    1.141行误用build函数(build是用的左闭右闭区间),输入了(a+1,a+n+1)。(然而不知道为什么虽然过不了udebug的数据然而把题目A掉了)

    2.没注意在字符前还是字符后插入

    *3.posib函数写错:没有考虑要计算hash值的串超出长度范围的情况(就是第二个"&&"之前的部分)。错了不止一次

    4.可能出现的错误:如果hash不用ull自然溢出,自己取模,那么要考虑爆int、爆longlong、负数等等

      1 #include<cstdio>
      2 #include<algorithm>
      3 using namespace std;
      4 inline int rand1()
      5 {
      6     static int x=471;
      7     return x=(48271LL*x+1)%2147483647;
      8 }
      9 unsigned long long powx[400010];
     10 struct Node
     11 {
     12     Node(){}
     13     Node* ch[2];
     14     int r;
     15     bool flip;
     16     int v;
     17     unsigned long long h,rh;
     18     int size;
     19     void upd()
     20     {
     21         if(ch[0])   ch[0]->pd();
     22         if(ch[1])   ch[1]->pd();
     23         size=1+(ch[0]?ch[0]->size:0)+(ch[1]?ch[1]->size:0);
     24         h=(ch[0]?ch[0]->h:0)+v*powx[ch[0]?ch[0]->size:0]+(ch[1]?ch[1]->h:0)*powx[(ch[0]?ch[0]->size:0)+1];
     25         rh=(ch[1]?ch[1]->rh:0)+v*powx[ch[1]?ch[1]->size:0]+(ch[0]?ch[0]->rh:0)*powx[(ch[1]?ch[1]->size:0)+1];
     26     }
     27     void pd()
     28     {
     29         if(flip)
     30         {
     31             swap(ch[0],ch[1]);
     32             swap(h,rh);
     33             if(ch[0])   (ch[0]->flip)^=1;
     34             if(ch[1])   (ch[1]->flip)^=1;
     35             flip=0;
     36         }
     37     }
     38 }nodes[400010];
     39 Node* root;int mem;
     40 Node* getnode(){return nodes+(mem++);}
     41 Node* merge(Node* a,Node* b)
     42 {
     43     if(a==NULL)    return b;
     44     if(b==NULL)    return a;
     45     if(a->r < b->r)
     46     {
     47         a->pd();a->ch[1]=merge(a->ch[1],b);a->upd();
     48         return a;
     49     }
     50     else
     51     {
     52         b->pd();b->ch[0]=merge(a,b->ch[0]);b->upd();
     53         return b;
     54     }
     55 }
     56 typedef pair<Node*,Node*> P;
     57 P split(Node* a,int n)
     58 {
     59     if(a==NULL)    return P(NULL,NULL);
     60     P y;
     61     a->pd();int s=a->ch[0] ? a->ch[0]->size : 0;
     62     if(s>=n)
     63     {
     64         y=split(a->ch[0],n);
     65         a->ch[0]=y.second;a->upd();
     66         y.second=a;
     67     }
     68     else
     69     {
     70         y=split(a->ch[1],n-s-1);
     71         a->ch[1]=y.first;a->upd();
     72         y.first=a;
     73     }
     74     return y;
     75 }
     76 inline void insert(int k,int x)
     77 {
     78     Node* t=getnode();
     79     t->ch[0]=t->ch[1]=NULL;t->r=rand1();t->v=x;t->flip=0;t->upd();
     80     P y=split(root,k-1);
     81     root=merge(merge(y.first,t),y.second);
     82 }
     83 inline void erase(int k)
     84 {
     85     P y=split(root,k-1);
     86     P y2=split(y.second,1);
     87     root=merge(y.first,y2.second);
     88 }
     89 inline void reverse(int l,int r)
     90 {
     91     if(l>r) swap(l,r);
     92     P y=split(root,l-1);
     93     P y2=split(y.second,r-l+1);
     94     y2.first->flip^=1;
     95     root=merge(merge(y.first,y2.first),y2.second);
     96 }
     97 inline int size()
     98 {
     99     return root ? root->size : 0;
    100 }
    101 inline unsigned long long geth(int l,int r)
    102 {
    103     if(l>r)  return 0;
    104     P y=split(root,l-1);
    105     P y2=split(y.second,r-l+1);
    106     unsigned long long ans=y2.first ? y2.first->h : 0;
    107     root=merge(merge(y.first,y2.first),y2.second);
    108     return ans;
    109 }
    110 Node* build(int *l,int *r)
    111 {
    112     if(l>r) return NULL;
    113     if(l==r)
    114     {
    115         Node* t=getnode();
    116         t->ch[0]=t->ch[1]=NULL;t->r=rand1();t->v=*l;t->flip=0;t->upd();
    117         return t;
    118     }
    119     else
    120     {
    121         int* mid=l+(r-l)/2;
    122         return merge(build(l,mid),build(mid+1,r));
    123     }
    124 }
    125 int n,m,q;
    126 int a[200010];
    127 const int X=127;
    128 int l,r;
    129 inline bool posib(int x)
    130 {
    131     return (l+x-1<=size())&&(r+x-1<=size())&&(geth(l,l+x-1)==geth(r,r+x-1));
    132 }
    133 int main()
    134 {
    135     register int i;
    136     int lx,rx,k,x,mid,tmp;
    137     powx[0]=1;
    138     for(i=1;i<=400000;i++)  powx[i]=powx[i-1]*X;
    139     scanf("%d%d",&n,&q);
    140     for(i=1;i<=n;i++)    scanf("%1d",&a[i]);
    141     root=build(a+1,a+n);
    142     while(q--)
    143     {
    144         scanf("%d",&tmp);
    145         if(tmp==1)
    146         {
    147             scanf("%d%d",&k,&x);
    148             insert(k+1,x);
    149         }
    150         else if(tmp==2)
    151         {
    152             scanf("%d",&k);
    153             erase(k);
    154         }
    155         else if(tmp==3)
    156         {
    157             scanf("%d%d",&l,&r);
    158             reverse(l,r);
    159         }
    160         else if(tmp==4)
    161         {
    162             scanf("%d%d",&l,&r);
    163             lx=0;rx=size()+1;
    164             while(rx-lx>1)
    165             {
    166                 mid=(lx+rx)>>1;
    167                 if(posib(mid))  lx=mid;
    168                 else    rx=mid;
    169             }
    170             printf("%d
    ",lx);
    171         }
    172     }
    173     return 0;
    174 }

    https://www.lydsy.com/JudgeOnline/problem.php?id=1014

    https://www.luogu.org/problemnew/show/P4036

    贴一下常数超大的代码

    做法类似

      1 #pragma GCC optimize("Ofast")
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cstring>
      5 using namespace std;
      6 inline int rand1()
      7 {
      8     static int x=471;
      9     return x=(48271LL*x+1)%2147483647;
     10 }
     11 unsigned long long powx[100010];
     12 struct Node
     13 {
     14     Node(){}
     15     Node* ch[2];
     16     int r;
     17     int v;
     18     unsigned long long h;
     19     int size;
     20     void upd()
     21     {
     22         size=1+(ch[0]?ch[0]->size:0)+(ch[1]?ch[1]->size:0);
     23         h=(ch[0]?ch[0]->h:0)+v*powx[ch[0]?ch[0]->size:0]+(ch[1]?ch[1]->h:0)*powx[(ch[0]?ch[0]->size:0)+1];
     24     }
     25 }nodes[250010];
     26 Node* root;int mem;
     27 Node* getnode(){return nodes+(mem++);}
     28 Node* merge(Node* a,Node* b)
     29 {
     30     if(a==NULL)    return b;
     31     if(b==NULL)    return a;
     32     if(a->r < b->r)
     33     {
     34         a->ch[1]=merge(a->ch[1],b);a->upd();
     35         return a;
     36     }
     37     else
     38     {
     39         b->ch[0]=merge(a,b->ch[0]);b->upd();
     40         return b;
     41     }
     42 }
     43 typedef pair<Node*,Node*> P;
     44 P split(Node* a,int n)
     45 {
     46     if(a==NULL)    return P(NULL,NULL);
     47     P y;
     48     int s=a->ch[0] ? a->ch[0]->size : 0;
     49     if(s>=n)
     50     {
     51         y=split(a->ch[0],n);
     52         a->ch[0]=y.second;a->upd();
     53         y.second=a;
     54     }
     55     else
     56     {
     57         y=split(a->ch[1],n-s-1);
     58         a->ch[1]=y.first;a->upd();
     59         y.first=a;
     60     }
     61     return y;
     62 }
     63 inline void insert(int k,int x)
     64 {
     65     Node* t=getnode();
     66     t->r=rand1();t->v=x;t->upd();
     67     P y=split(root,k-1);
     68     root=merge(merge(y.first,t),y.second);
     69 }
     70 inline void erase(int k)
     71 {
     72     P y=split(root,k-1);
     73     P y2=split(y.second,1);
     74     root=merge(y.first,y2.second);
     75 }
     76  
     77 inline int size()
     78 {
     79     return root ? root->size : 0;
     80 }
     81 inline unsigned long long geth(int l,int r)
     82 {
     83     if(l>r)  return 0;
     84     P y=split(root,l-1);
     85     P y2=split(y.second,r-l+1);
     86     unsigned long long ans=y2.first ? y2.first->h : 0;
     87     root=merge(merge(y.first,y2.first),y2.second);
     88     return ans;
     89 }
     90 Node* build(char *l,char *r)
     91 {
     92     if(l>r) return NULL;
     93     if(l==r)
     94     {
     95         Node* t=getnode();
     96         t->r=rand1();t->v=(int)(*l);t->upd();
     97         return t;
     98     }
     99     else
    100     {
    101         char* mid=l+(r-l)/2;
    102         return merge(build(l,mid),build(mid+1,r));
    103     }
    104 }
    105 int n,m,q;
    106 char a[100010];
    107 const int X=127;
    108 int l,r;
    109 char tmp;
    110 inline bool posib(int x)
    111 {
    112     return (l+x-1<=size())&&(r+x-1<=size())&&(geth(l,l+x-1)==geth(r,r+x-1));
    113 }
    114 int main()
    115 {
    116     register int i;
    117     int lx,rx,k,mid;
    118     powx[0]=1;
    119     for(i=1;i<=100000;i++)  powx[i]=powx[i-1]*X;
    120     scanf("%s",a+1);n=strlen(a+1);
    121     root=build(a+1,a+n);
    122     scanf("%d",&q);
    123     while(q--)
    124     {
    125         tmp=getchar();while(tmp<'A'||tmp>'Z') tmp=getchar();
    126         if(tmp=='I')
    127         {
    128             scanf("%d",&k);tmp=getchar();while(tmp<'a'||tmp>'z')  tmp=getchar();
    129             insert(k+1,(int)tmp);
    130         }
    131         else if(tmp=='R')
    132         {
    133             scanf("%d",&k);tmp=getchar();while(tmp<'a'||tmp>'z')  tmp=getchar();
    134             erase(k);insert(k,(int)tmp);
    135         }
    136         else if(tmp=='Q')
    137         {
    138             scanf("%d%d",&l,&r);
    139             lx=0;rx=size()+1;
    140             while(rx-lx>1)
    141             {
    142                 mid=(lx+rx)>>1;
    143                 if(posib(mid))  lx=mid;
    144                 else    rx=mid;
    145             }
    146             printf("%d
    ",lx);
    147         }
    148     }
    149     return 0;
    150 }
  • 相关阅读:
    模块二 GO语言进阶技术-panic函数、recover函数以及defer语句(上)
    模块二 GO语言进阶技术-错误处理(下)
    模块二 GO语言进阶技术-错误处理(上)
    模块二 GO语言进阶技术-if语句、for语句和switch语句
    模块二 GO语言进阶技术-GO语句及其执行规则(下)
    模块二 GO语言进阶技术-go语句及其执行规则(上)
    模块二 GO语言进阶技术-关于指针的有限操作
    模块二 GO语言进阶技术-接口类型的合理运用
    模块二 GO语言进阶技术-结构体及其方法的使用法门
    模块二 GO语言进阶技术-使用函数的正确姿势
  • 原文地址:https://www.cnblogs.com/hehe54321/p/8480849.html
Copyright © 2020-2023  润新知