zoukankan      html  css  js  c++  java
  • JSOI2008 火星人

    传送门

    这道题的话……首先得知道怎么求(LCP)。我们的方法首先二分一个长度,之后判断一下该区间内两段字符串的(hash)值是否相等,这样就可以啦。

    然后本题还要求支持插入和修改字母,所以我们需要使用一棵(splay)来维护(hash)值。具体做法是动态维护每一个节点的子树的(hash)值,在合并的时候,有(hash[x] = hash[l] imes base^{size[r]+1} + (s[x] - 'a') imes base^{size[r]} + hash[r]),这样修改就可以了。

    然后本题的建树可以直接建成完美的(splay),之后插入的时候先把要插入的位置(splay)出来之后插到右子树上。计算(hash)值的时候就(splay)一段区间出来取(hash)值就可以了。

    做这道题的时候发现了长久以来的问题……更新的时候要先更新儿子后更新父亲……以前模板题怎么写都能过,但是这题先更新父亲会RE……debug了好久。注意在头尾各插入了一个无用字符,以防止出错。

    看一下代码。

    #include<iostream>
    #include<cstdio>
    #include<cmath>
    #include<algorithm>
    #include<queue>
    #include<cstring>
    #define rep(i,a,n) for(int i = a;i <= n;i++)
    #define per(i,n,a) for(int i = n;i >= a;i--)
    #define enter putchar('
    ')
    #define de putchar('#')
    #define pr pair<int,int>
    #define mp make_pair
    #define fi first
    #define sc second
    #define B puts("GG")
    using namespace std;
    typedef long long ll;
    typedef unsigned long long ull;
    const int M = 200005;
    const int N = 10000005;
    const int INF = 1000000009;
    const ull base = 47;
     
    int read()
    {
       int ans = 0,op = 1;
       char ch = getchar();
       while(ch < '0' || ch > '9')
       {
          if(ch == '-') op = -1;
          ch = getchar();
       }
       while(ch >='0' && ch <= '9')
       {
          ans *= 10;
          ans += ch - '0';
          ch = getchar();
       }
       return ans * op;
    }
    
    struct node
    {
       int fa,ch[2],size;
       ull hash,val;
       char c;
    }t[M<<1];
    
    int n,m,x,y,root,idx,cnt;
    ull po[M];
    char s[M],a[5];
    
    bool get(int x)
    {
       return t[t[x].fa].ch[1] == x;
    }
    
    void update(int x)
    {
       int lson = t[x].ch[0],rson = t[x].ch[1];
       t[x].hash = t[lson].hash * po[t[rson].size+1] + t[x].val * po[t[rson].size] + t[rson].hash;
       t[x].size = t[lson].size + t[rson].size + 1;
    }
    
    void rotate(int x)
    {
       int y = t[x].fa,z = t[y].fa,k = get(x);
       t[z].ch[get(y)] = x,t[x].fa = z;
       t[y].ch[k] = t[x].ch[k^1],t[t[y].ch[k]].fa = y;
       t[x].ch[k^1] = y,t[y].fa = x;
       update(y),update(x);
    }
    
    void splay(int x,int goal)
    {
       while(t[x].fa != goal)
       {
          int y = t[x].fa,z = t[y].fa;
          if(z != goal) (t[y].ch[0] == x) ^ (t[z].ch[0] == y) ? rotate(x) : rotate(y);
          rotate(x);
       }
       if(!goal) root = x;
    }
    
    int build(int f,int l,int r)
    {
       if(l > r) return 0;
       int mid = (l+r) >> 1,u = ++cnt;
       t[u].val = s[mid] - 'a' + 1,t[u].fa = f,t[u].c = s[mid];
       t[u].ch[0] = build(u,l,mid-1),t[u].ch[1] = build(u,mid+1,r);
       update(u);
       return u;
    }
    
    int find(int x)
    {
       int u = root;
       while(1)
       {
          if(x <= t[t[u].ch[0]].size) u = t[u].ch[0];
          else if(x == t[t[u].ch[0]].size+1) return u;
          else x -= (t[t[u].ch[0]].size + 1),u = t[u].ch[1];
       }
    }
    
    void modify(int x)
    {
       int g = find(x);
       splay(g,0),t[g].val = a[0] - 'a' + 1,t[g].c = a[0],update(g);
    }
    
    void insert(int x)
    {
       int g = find(x),h = find(x+1);
       splay(g,0),splay(h,g);
       int u = ++idx;
       t[h].ch[0] = u,t[u].size = 1,t[u].val = t[u].hash = a[0] - 'a' + 1,t[u].fa = h;
       t[u].ch[0] = t[u].ch[1] = 0;
       update(h),update(g);
    }
    
    bool judge(int x,int y,int k)
    {
       if(k == 0) return 1;
       int g = find(x-1),h = find(x+k);
       splay(g,0),splay(h,g);
       ull cur = t[t[h].ch[0]].hash;
       g = find(y-1),h = find(y+k);
       splay(g,0),splay(h,g);
       ull now = t[t[h].ch[0]].hash;
       return cur == now;
    }
    
    int query(int x,int y)
    {
       int L = 0,R = idx,ans = 0;
       while(L <= R)
       {
          int mid = (L + R) >> 1;
          if(x + mid > idx || y + mid > idx) {R = mid - 1;continue;}
          if(judge(x,y,mid)) ans = mid,L = mid + 1;
          else R = mid - 1;
       }
       return ans;
    }
    
    int main()
    {
       po[0] = 1;rep(i,1,M-2) po[i] = po[i-1] * base;
       scanf("%s",s+2),idx = strlen(s+2) + 2;
       s[1] = s[idx] = 'f',root = build(0,1,idx);
       m = read();
       rep(i,1,m)
       {
          scanf("%s",a),x = read() + 1;
          if(a[0] == 'Q') y = read() + 1,printf("%d
    ",query(x,y));
          if(a[0] == 'R') scanf("%s",a),modify(x);
          if(a[0] == 'I') scanf("%s",a),insert(x);
       }  
       return 0;
    }
     */
    
  • 相关阅读:
    node错误: primordials is not defined
    单片机TTL转RS232模块DB9数据线接口排针接口多接口方便连接
    单片机串口自适应电平5V TTL电平兼容转换3.3V电平串口转换NMOS管
    USB串口转RS485转换器工业级usb串口转RS485模块转换器串口通讯
    Kafka丢数据、重复消费、顺序消费的问题
    纪念第一次做的拉花拿铁
    《奢侈的理由》总结
    【算法框架套路】回溯算法(暴力穷举的艺术)
    svg中矩形旋转问题
    性能测试工具集锦
  • 原文地址:https://www.cnblogs.com/captain1/p/10096542.html
Copyright © 2011-2022 走看看