【BZOJ1014】火星人(Splay,哈希)

题面

BZOJ

题解

要动态维护这个串,一脸的平衡树。

那么用\(Splay\)维护这个哈希值就好了。

每次计算答案的时候二分+Splay计算区间哈希值,

时间复杂度\(O(nlog^2n)\)

#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<set>
#include<map>
#include<vector>
#include<queue>
using namespace std;
#define ull unsigned long long
#define ll long long
#define RG register
#define MAX 111111
#define ls (t[x].ch[0])
#define rs (t[x].ch[1])
const int base=2333;
inline int read()
{
RG int x=0,t=1;RG char ch=getchar();
while((ch<'0'||ch>'9')&&ch!='-')ch=getchar();
if(ch=='-')t=-1,ch=getchar();
while(ch<='9'&&ch>='0')x=x*10+ch-48,ch=getchar();
return x*t;
}
char ch[MAX];
ull pw[MAX];
int root,tot;
struct Node
{
int ch[2],ff,size,len;
ull v,Hash;
}t[MAX];
void pushup(int x)
{
t[x].size=t[ls].size+t[rs].size+1;
t[x].len=t[ls].len+t[rs].len+(x>2);
t[x].Hash=(t[ls].Hash*base+t[x].v)*pw[t[rs].len]+t[rs].Hash;
}
void rotate(int x)
{
int y=t[x].ff,z=t[y].ff;
int k=t[y].ch[1]==x;
t[z].ch[t[z].ch[1]==y]=x;t[x].ff=z;
t[y].ch[k]=t[x].ch[k^1];t[t[x].ch[k^1]].ff=y;
t[x].ch[k^1]=y;t[y].ff=x;
pushup(y);
}
void Splay(int x,int goal)
{
while(t[x].ff!=goal)
{
int y=t[x].ff,z=t[y].ff;
if(z!=goal)
(t[z].ch[0]==y)^(t[y].ch[0]==x)?rotate(x):rotate(y);
rotate(x);
}
if(!goal)root=x;pushup(x);
}
int Kth(int k)
{
int x=root;
while(233)
{
if(t[ls].size+1==k)return x;
if(t[ls].size+1<k)k-=t[ls].size+1,x=rs;
else x=ls;
}
}
ull Hash(int l,int len)
{
int L=Kth(l),R=Kth(l+len+1);
Splay(L,0);Splay(R,L);
return t[t[R].ch[0]].Hash;
}
int LCQ(int x,int y)
{
int l=0,r=tot-max(x,y)-1,ret=0;
while(l<=r)
{
int mid=(l+r)>>1;
if(Hash(x,mid)==Hash(y,mid))l=mid+1,ret=mid;
else r=mid-1;
}
return ret;
}
void insert(int x,int v)
{
int L=Kth(x+1),R=Kth(x+2);
Splay(L,0);Splay(R,L);
t[++tot].v=v;t[R].ch[0]=tot;
t[tot].ff=R;Splay(tot,0);
}
void Modify(int x,int v)
{
int L=Kth(x),R=Kth(x+2);
Splay(L,0);Splay(R,L);
t[t[R].ch[0]].v=v;pushup(t[R].ch[0]);
pushup(R);pushup(L);
}
int main()
{
pw[0]=1;for(int i=1;i<MAX;++i)pw[i]=pw[i-1]*base;
scanf("%s",ch+1);
t[1].ch[1]=2;t[2].ff=1;tot=2;root=1;pushup(2);pushup(1);
for(int i=1,l=strlen(ch+1);i<=l;++i)insert(i-1,ch[i]);
int Q=read(),x,y;
while(Q--)
{
scanf("%s",ch);
if(ch[0]=='Q')printf("%d\n",LCQ(read(),read()));
else if(ch[0]=='R'){x=read();scanf("%s",ch);y=ch[0];Modify(x,y);}
else{x=read();scanf("%s",ch);y=ch[0];insert(x,y);}
}
return 0;
}

【BZOJ1014】火星人(Splay,哈希)的更多相关文章

  1. BZOJ1014火星人prefix Splay維護序列 + 字符串哈希

    @[Splay, 哈希] Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:\(madamimadam\), 我们将这个字符串的各个字符予以标号 ...

  2. 无旋Treap - BZOJ1014火星人 & 可持久化版文艺平衡树

    !前置技能&概念! 二叉搜索树 一棵二叉树,对于任意子树,满足左子树中的任意节点对应元素小于根的对应元素,右子树中的任意节点对应元素大于根对应元素.换言之,就是满足中序遍历为依次访问节点对应元 ...

  3. BZOJ1014 JSOI2008火星人(splay+哈希)

    splay维护哈希值即可. #include<iostream> #include<cstdio> #include<cmath> #include<cstd ...

  4. BZOJ1014:[JSOI2008]火星人(Splay,hash)

    Description 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam, 我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 ...

  5. bzoj 1014 [JSOI2008]火星人prefix——splay+哈希

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=1014 用splay维护字符串,每个点记录子树的哈希值,然后二分查询. 二分不是把两个点的哈希 ...

  6. bzoj1014 火星人 (hash+splay+二分答案)

    求公共前缀的问题可以用hash+二分来解决,但这个是动态的,所以我们用平衡树来维护区间的hash值 复杂度$O(mlog^2n)$ #include<bits/stdc++.h> #def ...

  7. 【JSOI2008】火星人prefix 哈希 非旋转treap

    题目大意 就是给你一个字符串,有三种操作,共\(m\)个 \(Q~x~y\):询问第\(x\)个后缀和第\(y\)个后缀的LCP \(R~x~y\):把第\(x\)个字符改成\(y\) \(I~x~y ...

  8. BZOJ.1014.[JSOI2008]火星人(Splay 二分 Hash)

    题目链接 后缀数组显然不行啊.求LCP还可以哈希+二分,于是考虑用平衡树维护哈希值. \[某一节点的哈希值 = hs[lson]*base^{sz[rson]+1} + s[rt]*base^{sz[ ...

  9. bzoj1014火星人

    ...强迫症终于A了这道题  bzoj前30道全A指日可待 splay维护这个结点控制的字符串的hash值 每次旋转重新算一遍就可以了 查询的时候跑一个二分 讲起来很简单但是还是调了1h才调对了spl ...

  10. 【BZOJ1125】【POI2008】poc - splay+哈希

    题意: Description n列火车,每条有l节车厢.每节车厢有一种颜色(用小写字母表示).有m次车厢交换操作.求:对于每列火车,在交换车厢的某个时刻,与其颜色完全相同的火车最多有多少. Inpu ...

随机推荐

  1. Spring学习(四)-----Spring Bean引用同xml和不同xml bean的例子

    在Spring,bean可以“访问”对方通过bean配置文件指定相同或不同的引用. 1. Bean在不同的XML文件 如果是在不同XML文件中的bean,可以用一个“ref”标签,“bean”属性引用 ...

  2. Python小白学习之文件内建函数

    文件内建函数: 2018-10-24 23:40:02   简单介绍: open()打开文件 read()读取文件(其实是输入文件里的内容到read函数,类似于get(url),所以下面的图片备注的是 ...

  3. Swoole实现h5版聊天室笔记

    声明:该聊天室目前只有一对多,一对一的聊天功能,另外,因为没有使用到mysql,所以还存在比较多的缺陷地方,但知道原理就差不多了,这里主要分享下swoole简易的聊天室制作思路. 开发环境:cento ...

  4. Linux系统服务(daemon)(鸟哥Linux私房菜笔记)

    Linux系统服务(daemon) 一.SystemV的init管理机制(脚本式启动)1.服务启动分类stand alone 独立启动模式super daemon 总管程序 2.服务的启动.关闭与观察 ...

  5. 【转】AOE机制的DSL及其实际运用

    AOE这个词的意思,我相信玩过WOW的人都不陌生,包括玩过LoL的也不会陌生,说穿了就是一个区域内发生效果(Area of effect).这里我们要讨论的就是关于一个适合于几乎所有游戏的AOE机制, ...

  6. C++进阶训练——停车收费系统设计

    一.简介 经过一段时间的c++基础学习,是时候做一个较为全面的.运用c++功能的较复杂的项目练练手了. 运用软件:Visual Studio   (VS). 题目:c++停车收费系统设计(某本编程书进 ...

  7. How to pass an Amazon account review

    Have you ever sold products on Amazon? How about sold so much within the first week that amazon deci ...

  8. hbase 预分区

    转载 http://www.cnblogs.com/bdifn/p/3801737.html

  9. 第六次作业psp

    psp 进度条 代码累积折线图 博文累积折线图 psp饼状图

  10. 【Alpha】阶段第三次Scrum Meeting

    [Alpha]阶段第三次Scrum Meeting 工作情况 团队成员 今日已完成任务 明日待完成任务 刘峻辰 更新评论接口 获取课程评论接口 赵智源 编写脚本实现持续集成 整合前端进行部署 肖萌威 ...