• 【BZOJ】【1014】【JLOI2008】火星人prefix


    Splay/二分/Hash


      看了网上的题目关键字(都不用点进去看……我也是醉了)了解到做法= =那就上呗,前面做了好几道Splay的题就是为了练手搞这个的。

      Hash判断字符串是否相同应该很好理解吧?>_>我就不细说了

      二分这个相同前缀的长度应该也容易>_>

      用Splay维护这个Hash值>_>……也挺简单的,跟据size域就能算出以x为根的子树的hash值了。

      

      这次我终于发现了一个之前以为不太重要的点……让我WA了两次= =!!

      就是Splay在执行完序列插入的时候,一定要立即Push_up(c[root][1]); Push_up(root);不能想着别的操作随便splay一下自己就维护了……因为size域是会受到影响的!!

      1 /**************************************************************
      2     Problem: 1014
      3     User: Tunix
      4     Language: C++
      5     Result: Accepted
      6     Time:5600 ms
      7     Memory:13288 kb
      8 ****************************************************************/
      9  
     10 //BZOJ 1014
     11 #include<vector>
     12 #include<cstdio>
     13 #include<cstring>
     14 #include<cstdlib>
     15 #include<iostream>
     16 #include<algorithm>
     17 #define rep(i,n) for(int i=0;i<n;++i)
     18 #define F(i,j,n) for(int i=j;i<=n;++i)
     19 #define D(i,j,n) for(int i=j;i>=n;--i)
     20 #define pb push_back
     21 using namespace std;
     22 inline int getint(){
     23     int v=0,sign=1; char ch=getchar();
     24     while(ch<'0'||ch>'9'){ if (ch=='-') sign=-1; ch=getchar();}
     25     while(ch>='0'&&ch<='9'){ v=v*10+ch-'0'; ch=getchar();}
     26     return v*sign;
     27 }
     28 const int N=3e5+10,INF=~0u>>2;
     29 typedef long long LL;
     30 typedef unsigned long long u64;
     31 /******************tamplate*********************/
     32 int n,m;
     33 char s[N];
     34 int c[N][2],fa[N],size[N],tot,root;
     35 u64 sum[N],v[N],mi[N];
     36 #define L c[x][0]
     37 #define R c[x][1]
     38 void Push_up(int x){
     39     size[x]=size[L]+size[R]+1;
     40     sum[x]=sum[L]*mi[size[R]+1]+v[x]*mi[size[R]]+sum[R];
     41 }
     42 void Rotate(int x){
     43     int y=fa[x],z=fa[y],l=c[y][1]==x,r=l^1;
     44     c[z][c[z][1]==y]=x;
     45     fa[x]=z; fa[y]=x; fa[c[x][r]]=y;
     46     c[y][l]=c[x][r]; c[x][r]=y;
     47     Push_up(y);
     48 }
     49 void splay(int x,int s=0){
     50     int y;
     51     for(;fa[x]!=s;Rotate(x))
     52         if (fa[y=fa[x]]!=s) Rotate(c[y][1]==x^c[fa[y]][1]==y?x:y);
     53     Push_up(x);
     54     if (!s) root=x;
     55 }
     56 void New_node(int &x,int f,int key){
     57     x=++tot;
     58     fa[x]=f;
     59     v[x]=sum[x]=key; L=R=0;
     60     size[x]=1;
     61 }
     62 void Build(int &x,int f,int l,int r){
     63     if (l>r) return;
     64     int m=l+r>>1;
     65     New_node(x,f,s[m]);
     66     Build(L,x,l,m-1);
     67     Build(R,x,m+1,r);
     68     Push_up(x);
     69 }
     70 int kth(int x,int k){
     71     if (size[L]+1==k) return x;
     72     else if (size[L]>=k) return kth(L,k);
     73     else return kth(R,k-size[L]-1);
     74 }
     75 int query(int x1,int x2){
     76     int l=1,r=min(size[root]-x1,size[root]-x2)-1,mid,ans=0;
     77     //由于右侧有一个空白字符,所以要-1
     78     u64 n1=0,n2=0;
     79     while(l<=r){
     80         mid=l+r>>1;
     81         splay(kth(root,x1)); splay(kth(root,x1+mid+1),root);
     82         n1=sum[c[c[root][1]][0]];
     83         splay(kth(root,x2)); splay(kth(root,x2+mid+1),root);
     84         n2=sum[c[c[root][1]][0]];
     85         if (n1==n2) ans=mid,l=mid+1;
     86         else r=mid-1;
     87     }
     88     return ans;
     89 }
     90 int main(){
     91 #ifndef ONLINE_JUDGE
     92     freopen("1014.in","r",stdin);
     93     freopen("1014.out","w",stdout);
     94 #endif
     95     scanf("%s",s+1);
     96     n=strlen(s+1);
     97     mi[0]=1; F(i,1,n*3) mi[i]=mi[i-1]*131;
     98     s[0]=s[n+1]=0;
     99     Build(root,0,0,n+1);
    100     m=getint();
    101     char cmd[5],s1[5];
    102     int x,y;
    103     F(i,1,m){
    104         scanf("%s",cmd);
    105         if (cmd[0]=='Q'){
    106             x=getint(); y=getint();
    107             printf("%d
    ",query(x,y));
    108         }else if (cmd[0]=='R'){
    109             x=getint(); scanf("%s",s1);
    110             int pos=kth(root,x+1);
    111             v[pos]=s1[0];
    112             splay(pos);
    113         }else{
    114             x=getint()+1; scanf("%s",s1);
    115             splay(kth(root,x)); splay(kth(root,x+1),root);
    116             int &pos=c[c[root][1]][0];
    117             New_node(pos,c[root][1],s1[0]);
    118             Push_up(c[root][1]); Push_up(root);
    119         }
    120     }
    121     return 0;
    122 }
    View Code

    1014: [JSOI2008]火星人prefix

    Time Limit: 10 Sec  Memory Limit: 162 MB
    Submit: 3815  Solved: 1168
    [Submit][Status][Discuss]

    Description

    火 星人最近研究了一种操作:求一个字串两个后缀的公共前缀。比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序 号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人定义了一个函数LCQ(x, y),表示:该字符串中第x个字符开始的字串,与该字符串中第y个字符开始的字串,两个字串的公共前缀的长度。比方说,LCQ(1, 7) = 5, LCQ(2, 10) = 1, LCQ(4, 7) = 0 在研究LCQ函数的过程中,火星人发现了这样的一个关联:如果把该字符串的所有后缀排好序,就可以很快地求出LCQ函数的值;同样,如果求出了LCQ函数 的值,也可以很快地将该字符串的后缀排好序。 尽管火星人聪明地找到了求取LCQ函数的快速算法,但不甘心认输的地球人又给火星人出了个难题:在求取LCQ函数的同时,还可以改变字符串本身。具体地 说,可以更改字符串中某一个字符的值,也可以在字符串中的某一个位置插入一个字符。地球人想考验一下,在如此复杂的问题中,火星人是否还能够做到很快地求 取LCQ函数的值。

    Input

    第一行给出初始的字符串。第二行 是一个非负整数M,表示操作的个数。接下来的M行,每行描述一个操作。操作有3种,如下所示: 1、 询问。语法:Q x y,x, y均为正整数。功能:计算LCQ(x, y) 限制:1 <= x, y <= 当前字符串长度。 2、 修改。语法:R x d,x是正整数,d是字符。功能:将字符串中第x个数修改为字符d。限制:x不超过当前字符串长度。 3、 插入:语法:I x d,x是非负整数,d是字符。功能:在字符串第x个字符之后插入字符d,如果x = 0,则在字符串开头插入。限制:x不超过当前字符串长度。

    Output

    对于输入文件中每一个询问操作,你都应该输出对应的答案。一个答案一行。

    Sample Input

    madamimadam
    7
    Q 1 7
    Q 4 8
    Q 10 11
    R 3 a
    Q 1 7
    I 10 a
    Q 2 11

    Sample Output

    5
    1
    0
    2
    1

    HINT

    数据规模:

    对于100%的数据,满足:

    1、 所有字符串自始至终都只有小写字母构成。

    2、 M <= 150,000

    3、 字符串长度L自始至终都满足L <= 100,000

    4、 询问操作的个数不超过10,000个。

    对于第1,2个数据,字符串长度自始至终都不超过1,000

    对于第3,4,5个数据,没有插入操作。


    Source

    [Submit][Status][Discuss]
  • 相关阅读:
    详解prototype、proto和constructor的关系
    BFC
    transition(动画属性)
    React组件生命周期
    正则限制input只能输入大于0的数字
    msbuild编译
    python 在头文件添加 #include "stdafx.h"
    2017年感想
    chVsprintf
    富文本测试
  • 原文地址:https://www.cnblogs.com/Tunix/p/4415423.html
Copyright © 2020-2023  润新知