• [JSOI2008]火星人


    题目大意:
       给定一个只包含小写英文字母的字符串$s$,进行以下3种操作共$m(mleq150000)$次:
        1.改变某个位置上的字符;
        2.在某个位置插入一个字符;
        3.求两个后缀的LCS长度。
      保证操作过程中串长不超过$100000$。

    思路:
      Splay维护字符串及对应区间的Hash值,询问时二分答案即可。

    细节:
      不卡哈希不代表底数可以取偶数。

      1 #include<cstdio>
      2 #include<cctype>
      3 #include<cstring>
      4 #include<algorithm>
      5 typedef unsigned long long uint64;
      6 inline int getint() {
      7     register char ch;
      8     while(!isdigit(ch=getchar()));
      9     register int x=ch^'0';
     10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
     11     return x;
     12 }
     13 inline char getalpha() {
     14     register char ch;
     15     while(!isalpha(ch=getchar()));
     16     return ch;
     17 }
     18 const int N=100003,BASE=27;
     19 char s[N];
     20 int n;
     21 class SplayTree {
     22     private:
     23         int val[N],size[N],par[N],ch[N][2],root;
     24         uint64 hash[N],pow[N];
     25         int id(const char &c) const {
     26             return c-'a';
     27         }
     28         int sz,new_node(const int &x) {
     29             size[++sz]=1;
     30             val[sz]=x;
     31             return sz;
     32         }
     33         void push_up(const int &p) {
     34             size[p]=size[ch[p][0]]+size[ch[p][1]]+1;
     35             hash[p]=hash[ch[p][0]]+val[p]*pow[size[ch[p][0]]]+hash[ch[p][1]]*pow[size[ch[p][0]]+1];
     36         }
     37         void rotate(const int &x) {
     38             const int y=par[x],z=par[y];
     39             const bool b=x==ch[y][0];
     40             par[ch[x][b]=par[ch[y][!b]=ch[x][b]]=y]=x;
     41             par[ch[z][y==ch[z][1]]=x]=z;
     42             push_up(y),push_up(x);
     43         }
     44         void splay(int x,const int &goal) {
     45             for(register int y=par[x],z=par[y];y!=goal;rotate(x),z=par[y=par[x]]) {
     46                 if(z!=goal) rotate((x==ch[y][0])^(y==ch[z][0])?x:y);
     47             }
     48             if(!goal) root=x;
     49         }
     50         int find(int x) {
     51             for(register int y=root;;y=ch[y][size[ch[y][0]]+1<x]) {
     52                 if(y!=root&&y==ch[par[y]][1]) x-=size[ch[par[y]][0]]+1;
     53                 if(size[ch[y][0]]+1==x) return y;
     54             }
     55         }
     56         uint64 calc(const int &l,const int &r) {
     57             splay(find(l),0);
     58             splay(find(r+2),root);
     59             return hash[ch[ch[root][1]][0]];
     60         }
     61     public:
     62         void build() {
     63             for(register int i=pow[0]=1;i<N;i++) {
     64                 pow[i]=pow[i-1]*BASE;
     65             }
     66             for(register int i=ch[0][1]=1;i<=n;i++) {
     67                 par[ch[i][1]=i+1]=i;
     68                 val[i+1]=id(s[i]);
     69             }
     70             par[sz=ch[n+1][1]=n+2]=n+1;
     71             size[n+2]=1;
     72             splay(n+2,0);
     73         }
     74         int query(const int &x,const int &y) {
     75             int l=0,r=sz-std::max(x,y)-1;
     76             while(l<=r) {
     77                 const int mid=(l+r)>>1;
     78                 if(calc(x,x+mid-1)==calc(y,y+mid-1)) {
     79                     l=mid+1;
     80                 } else {
     81                     r=mid-1;
     82                 }
     83             }
     84             return l-1;
     85         }
     86         void modify(const int &x,const char &c) {
     87             splay(find(x),0);
     88             splay(find(x+2),root);
     89             val[ch[ch[root][1]][0]]=id(c);
     90             splay(ch[ch[root][1]][0],0);
     91         }
     92         void insert(const int &x,const char &c) {
     93             splay(find(x+1),0);
     94             splay(find(x+2),root);
     95             par[ch[ch[root][1]][0]=new_node(id(c))]=ch[root][1];
     96             splay(ch[ch[root][1]][0],0);
     97         }
     98 };
     99 SplayTree t;
    100 int main() {
    101     scanf("%s",&s[1]);
    102     n=strlen(&s[1]);
    103     t.build();
    104     for(register int i=getint();i;i--) {
    105         const int opt=getalpha(),x=getint();
    106         if(opt=='Q') printf("%d
    ",t.query(x,getint()));
    107         if(opt=='R') t.modify(x,getalpha());
    108         if(opt=='I') t.insert(x,getalpha());
    109     }
    110     return 0;
    111 }
  • 相关阅读:
    我的又一个web2.0作品
    AjaxPro使用注意事项与返回数据库中数据时2.0和3.5/4.0的区别(我的心得)
    AjaxPro入门使用方法
    SQLHelper的简单应用,高手绕道,写出最近用的一个类,仅供初学者参考
    Notepad++插件NPPExec编译运行C++、JAVA和Python代码
    在Ubuntu 18.04 LTS上搭建SS并启用BBR
    Linux 目录和文件管理
    chap06
    三层交换机的VLAN划分
    传输协议
  • 原文地址:https://www.cnblogs.com/skylee03/p/8522469.html
Copyright © 2020-2023  润新知