类似于1014,用splay维护这个序列,维护每个节点为根的子树的hash值,对于一个询问二分答案判断就行了。

  反思:询问的时候因为是原序列的x,y,所以开始的时候直接splay(x-1)了,后来发现这是不对的,因为可能在x前插入一些东西,所以需要麻烦些,先splay(x),然后提出来右端点为size[son[rot][0]]+1+len,然后再splay(find(size[son[rot][0]]+1))。

/**************************************************************
    Problem: 2258
    User: BLADEVIL
    Language: C++
    Result: Accepted
    Time:7904 ms
    Memory:3640 kb
****************************************************************/
 
//By BLADEVIL
#include <cstdio>
#include <cstring>
#include <algorithm>
#define maxn 100010
 
using namespace std;
 
char s[maxn];
int fac[maxn],key[maxn],num,rot,son[maxn][],father[maxn],size[maxn],hash[maxn];
 
void update(int x) {
    if (!x) return ;
    hash[x]=hash[son[x][]]+(key[x]+hash[son[x][]]*)*fac[size[son[x][]]];
    size[x]=size[son[x][]]+size[son[x][]]+;
}
 
int build(int l,int r) {
    int mid=l+r>>,left=,right=;
    if (mid<r) right=build(mid+,r);
    if (mid>l) left=build(l,mid-);
    father[left]=father[right]=mid;
    son[mid][]=left; son[mid][]=right;
    update(mid);
    return mid;
}
 
void rotate(int x,int &rot) {
    int y=father[x],z=father[y];
    int p=(son[y][]==x),q=p^;
    if (y==rot) rot=x; else if (son[z][]==y) son[z][]=x; else son[z][]=x;
    father[x]=z; father[y]=x; father[son[x][q]]=y;
    son[y][p]=son[x][q]; son[x][q]=y;
    update(y);
}
 
void splay(int x,int &rot) {
    while (x!=rot) {
        int y=father[x],z=father[y];
        if (y!=rot)
            if ((son[y][]==x)^(son[z][]==y)) rotate(x,rot); else rotate(y,rot);
        rotate(x,rot);
    }
    update(x);
}
 
int find(int x) {
    int t=rot;
    while () {
        if (size[son[t][]]+==x) return t; else
        if (size[son[t][]]+>x) t=son[t][]; else
        if (size[son[t][]]+<x) x-=size[son[t][]]+,t=son[t][];
    }
}
 
bool judge(int x,int y,int len) {
    if (len==) return key[x+]==key[y+];
    int p=x+; splay(p,rot);
    int q=find(size[son[rot][]]++len);
    splay(find(size[son[rot][]]),rot); splay(q,son[rot][]);
    int a1=hash[son[q][]];
    p=y+; splay(p,rot);
    q=find(size[son[rot][]]++len);
    splay(find(size[son[rot][]]),rot); splay(q,son[rot][]);
    int a2=hash[son[q][]];
    return a1==a2;
}
 
int main() {
    scanf("%s",s); num=strlen(s);
    fac[]=; for (int i=;i<maxn;i++) fac[i]=fac[i-]*;
    for (int i=;i<=num+;i++) key[i]=s[i-]-'a'+; num+=;
    rot=build(,num);
    int task; scanf("%d",&task);
    while (task--) {
        int x,y;
        scanf("%s",s);
        if (s[]=='Q') {
            scanf("%d%d",&x,&y);
            if (x>y) swap(x,y);
            splay(y+,rot);
            int l=,r=size[son[rot][]],mid,ans=;
            while (l<=r) {
                mid=l+r>>;
                if (judge(x,y,mid)) ans=mid, l=mid+; else r=mid-;
            }
            printf("%d\n",ans);
        } else
        if (s[]=='I') {
            scanf("%s%d",s,&x);
            x=(x>num-)?num:x;
            key[++num]=s[]-'a'+;
            int p=find(x); splay(p,rot);
            int q=find(x+); splay(q,son[rot][]);
            father[num]=q; son[q][]=num;
            splay(num,rot);
        }
    }
    return ;  
}

bzoj 2258 splay的更多相关文章

  1. bzoj 1269 bzoj 1507 Splay处理文本信息

    bzoj 1269 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=1269 大致思路: 用splay维护整个文本信息,splay树的中序遍历即为 ...

  2. bzoj 3506 && bzoj 1552 splay

    查最小值,删除,翻转... 显然splay啊... #include<iostream> #include<cstdio> #include<algorithm> ...

  3. bzoj 1014 splay维护hash值

    被后缀三人组虐了一下午,写道水题愉悦身心. 题很裸,求lcq时二分下答案就行了,写的不优美会被卡时. (写题时精神恍惚,不知不觉写了快两百行...竟然调都没调就A了...我还是继续看后缀自动机吧... ...

  4. bzoj 1503 splay

    因为是整体加减,所以直接记录在外面. #include<iostream> #include<cstdio> #include<cstring> #include& ...

  5. bzoj 3224 splay模板题4

    再刷水题我就废了... #include<iostream> #include<cstdio> #include<algorithm> #include<cs ...

  6. bzoj 3223 splay模板题3

    水题...貌似理解splay怎么维护数列了... 每个点维护一个size,它的位置就是它的size,区间翻转的话可以打标记,find的时候push_down,交换左右子树. #include<i ...

  7. bzoj 1208 splay模板题2

    自己yy了找前驱和后继,学了学怎么删除...(反正就是练模板) #include<iostream> #include<cstdio> #include<cstring& ...

  8. bzoj 1588 splay模板题

    用晚自习学了一下splay模板,没想象中那么难,主要是左旋和右旋可以简化到一个函数里边,减少代码长度... #include<iostream> #include<cstdio> ...

  9. BZOJ 2733 & splay的合并

    题意: 带权联通块,添边与查询联通块中第k大. SOL: splay合并+并查集. 我以为splay可以用奇技淫巧来简单合并...调了一下午终于幡然醒悟...于是就只好一个一个慢慢插...什么启发式合 ...

随机推荐

  1. G# GUID

    GUID(全局统一标识符)是指在一台机器上生成的数字,它保证对在同一时空中的所有机器都是唯一的.通常平台会提供生成GUID的API.生成算法很有意思,用到了以太网卡地址.纳秒级时间.芯片ID码和许多可 ...

  2. 2019 front end jobs collection

    2019 front end jobs collection Alibaba https://ant.design/docs/spec/work-with-us-cn https://www.yuqu ...

  3. BZOJ 1818 内部白点(离散化+树状数组)

    此题就是1227 的弱化版. 画个图或者稍微证明一下就能够知道,一定不会超过一次变换. 那么我们只需要统计有多少个白点会变黑,换句话说就是有多少个白点上下左右都有黑点. 离散化横坐标,因为没有黑点在的 ...

  4. BZOJ 1486 最小圈(01分数规划)

    好像是很normal的01分数规划题.最小比率生成环. u(c)=sigma(E)/k.转化一下就是k*u(c)=sigma(E). sigma(E-u(c))=0. 所以答案对于这个式子是有单调性的 ...

  5. 【bzoj1609】[Usaco2008 Feb]Eating Together麻烦的聚餐 dp

    题目描述 为了避免餐厅过分拥挤,FJ要求奶牛们分3批就餐.每天晚饭前,奶牛们都会在餐厅前排队入内,按FJ的设想所有第3批就餐的奶牛排在队尾,队伍的前端由设定为第1批就餐的奶牛占据,中间的位置就归第2批 ...

  6. Atom Editor 插件 atom-less 的使用方法

    一.下载安装 atom-less atom-less 项目在这里:https://github.com/schmuli/atom-less 安装方法请参考这篇博文:http://blog.csdn.n ...

  7. Select-poll-epoll-简介

    1. Python的select()方法直接调用操作系统的IO接口,它监控sockets,open files, and pipes(所有带fileno()方法的文件句柄)何时变成readable 和 ...

  8. [洛谷P4735]最大异或和

    题目大意:有一串初始长度为$n$的序列$a$,有两种操作: $A\;x:$在序列末尾加一个数$x$ $Q\;l\;r\;x:$找一个位置$p$,满足$l\leqslant p\leqslant r$, ...

  9. POJ3177:Redundant Paths——题解

    http://poj.org/problem?id=3177 明显要求桥的一道题. (因为有桥就说明只能从那一条路走,换句话说就是只有一种方法) 求完桥后按照结论(加几条边成双连通图的结论,不会请ba ...

  10. BZOJ5285 & 洛谷4424 & UOJ384:[HNOI/AHOI2018]寻宝游戏——题解

    https://www.lydsy.com/JudgeOnline/problem.php?id=5285 https://www.luogu.org/problemnew/show/P4424 ht ...