[JSOI2008]火星人
嘟嘟嘟
嗯。
splay维护哈希。
如题,用splay维护哈希,查找的时候二分。所以复杂度是取决于询问复杂度:\(O(n \log^ 2{n})\)。
这道题还有一个技巧,就是一个节点记录的是他的子树的哈希值,所以树的的形态改变的同时,每一个节点记录的哈希值也在改变。在pushup的时候,应该这么写:\(t[now].has = t[l].has * base ^ {t[r].siz + 1} + (s[now] - 'a') * base ^ {t[r].siz} + t[r].has\)。
然后好像就没什么好说的啦,各种操作的中心思想都是通过旋转前驱后继提取区间。
然后注意\(base\)别取字符集大小,我因为取了\(26\)导致大的点没过去,应该是取的太小导致冲突的概率比较大吧。
然而取\(27\)就过了~
#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define rg register
typedef long long ll;
typedef unsigned long long ull;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 1e5 + 5;
inline ll read()
{
ll ans = 0;
char ch = getchar(), last = ' ';
while(!isdigit(ch)) last = ch, ch = getchar();
while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
if(last == '-') ans = -ans;
return ans;
}
inline void write(ll x)
{
if(x < 0) x = -x, putchar('-');
if(x >= 10) write(x / 10);
putchar(x % 10 + '0');
}
int m;
ull p[maxn];
char s[maxn], c[2], tp[2];
struct Tree
{
int ch[2], fa;
int siz; ull has;
}t[maxn];
int root, ncnt = 0;
void _PrintTr(int now)
{
if(!now) return;
printf("nd:%d ls:%d rs:%d\n", now, t[now].ch[0], t[now].ch[1]);
_PrintTr(t[now].ch[0]); _PrintTr(t[now].ch[1]);
}
void pushup(int now)
{
int l = t[now].ch[0], r = t[now].ch[1];
t[now].siz = t[l].siz + t[r].siz + 1;
t[now].has = t[l].has * p[t[r].siz + 1] + (s[now] - 'a') * p[t[r].siz] + t[r].has;
}
void rotate(int x)
{
int y = t[x].fa, z = t[y].fa, k = (t[y].ch[1] == x);
t[z].ch[t[z].ch[1] == 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;
pushup(y); pushup(x);
}
void splay(int x, int s)
{
while(t[x].fa != s)
{
int y = t[x].fa, z = t[y].fa;
if(z != s)
{
if((t[z].ch[0] == y) ^ (t[y].ch[0] == x)) rotate(x);
else rotate(y);
}
rotate(x);
}
if(!s) root = x;
}
void build(int L, int R, int f)
{
if(L > R) return;
int mid = (L + R) >> 1;
if(L == R) t[L].siz = 1, t[L].has = s[L] - 'a';
else build(L, mid - 1, mid), build(mid + 1, R, mid);
t[f].ch[mid > f] = mid; t[mid].fa = f;
pushup(mid);
}
int rnk(int k)
{
int now = root;
while(1)
{
if(k <= t[t[now].ch[0]].siz) now = t[now].ch[0];
else if(k == t[t[now].ch[0]].siz + 1) return now;
else k -= (t[t[now].ch[0]].siz + 1), now = t[now].ch[1];
}
}
void update(int x)
{
int now = rnk(x); splay(now, 0);
s[now] = tp[0];
pushup(now);
}
void insert(int x)
{
int a = rnk(x), b = rnk(x + 1);
splay(a, 0); splay(b, a);
s[++ncnt] = tp[0];
t[ncnt].has = tp[0] - 'a';
t[ncnt].siz = 1;
t[ncnt].ch[0] = t[ncnt].ch[1] = 0;
t[b].ch[0] = ncnt; t[ncnt].fa = b;
pushup(b); pushup(a);
}
bool judge(int x, int y, int len)
{
if(x + len > ncnt || y + len > ncnt) return 0;
int a = rnk(x - 1), b = rnk(x + len);
splay(a, 0); splay(b, a);
//_PrintTr(root);
//puts("~~~~~~~~~~~~~~~~~~");
ull has1 = t[t[b].ch[0]].has;
a = rnk(y - 1), b = rnk(y + len);
splay(a, 0); splay(b, a);
//_PrintTr(root);
ull has2 = t[t[b].ch[0]].has;
return has1 == has2;
}
int query(int x, int y)
{
int L = 0, R = ncnt;
while(L < R)
{
int mid = (L + R + 1) >> 1;
if(judge(x, y, mid)) L = mid;
else R = mid - 1;
}
return L;
}
int main()
{
p[0] = 1; for(int i = 1; i < maxn; ++i) p[i] = p[i - 1] * 47; //学姐强啊
scanf("%s", s + 2); ncnt = strlen(s + 2) + 2;
s[1] = s[ncnt] = 'f';
build(1, ncnt, 0);
for(int i = 1; i <= ncnt && !root; ++i) if(!t[i].fa) root = i;
m = read();
for(int i = 1, x; i <= m; ++i)
{
scanf("%s", c); x = read() + 1;
if(c[0] == 'Q')
{
int y = read() + 1;
write(query(x, y)), enter;
}
else
{
scanf("%s", tp);
if(c[0] == 'R') update(x);
else insert(x);
}
//_PrintTr(root);
}
return 0;
}
[JSOI2008]火星人的更多相关文章
- 1014: [JSOI2008]火星人prefix
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MB Description 火星人最近研究了一种操作:求一个字串两个后缀 ...
- [BZOJ1014][JSOI2008]火星人prefix
[BZOJ1014][JSOI2008]火星人prefix 试题描述 火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字 ...
- BZOJ 1014: [JSOI2008]火星人prefix [splay 二分+hash] 【未完】
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 6243 Solved: 2007[Submit] ...
- 【bzoj1014】[JSOI2008]火星人prefix
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 6031 Solved: 1917[Submit] ...
- BZOJ 1014: [JSOI2008]火星人prefix Splay+二分
1014: [JSOI2008]火星人prefix 题目连接: http://www.lydsy.com/JudgeOnline/problem.php?id=1014 Description 火星人 ...
- JSOI2008 火星人prefix
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 2918 Solved: 866[Submit][ ...
- bzoj 1014: [JSOI2008]火星人prefix hash && splay
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 3154 Solved: 948[Submit][ ...
- 求帮看!!!!BZOJ 1014 [JSOI2008]火星人prefix
1014: [JSOI2008]火星人prefix Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 4164 Solved: 1277[Submit] ...
- BZOJ 1014: [JSOI2008]火星人prefix( splay + hash )
用splay维护序列, 二分+hash来判断LCQ.. #include<bits/stdc++.h> using namespace std; typedef unsigned long ...
- BZOJ_1014_[JSOI2008]火星人prefix_splay+hash
BZOJ_1014_[JSOI2008]火星人prefix_splay+hash 题意:火星人最近研究了一种操作:求一个字串两个后缀的公共前缀.比方说,有这样一个字符串:madamimadam, 我们 ...
随机推荐
- 设置navigationbar透明度时的坑
1.需要设置导航条透明度时 UIImage *image = [UIImage imageNamed:@"bg_clear.png"]; //设置背景颜色 [nav2.na ...
- Java 使用new Thread和线程池的区别
本文转至:https://www.cnblogs.com/cnmenglang/p/6273761.html , 孟凡柱的专栏 的博客,在此谢谢博主! 1.new Thread的弊端执行一个异步任务你 ...
- K:Treap(堆树)
Treap=Tree+Heap.Treap是一棵二叉排序树,它的左子树和右子树分别是一个Treap,和一般的二叉排序树不同的是, Treap记录一个额外的数据, 就是优先级.Treap在以关键码构 ...
- mac,macbook 连接蓝牙耳机播放音乐断断续续
个人的情况是, mac本连的网线,用的无线鼠标, 屋里80多号人都在用笔记本,应该也有好多开着无线的东西 解决方法: mac 或macbook 连接蓝牙耳机播放音乐断断续续的原因, 在网上找了好多方法 ...
- c#中表达式的返回值是啥?
今天在学javascript的时候发现它其中有一个语法是这样的(a="haha).length;这样也能够输出haha这个字符串的长度,然而我在使用c#的时候分行读取txt文本的时候也用这个 ...
- 线上Bug修复流程
- animation 秒简单笔记
<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8&quo ...
- 浏览器根对象navigator之客户端检测
Navigator的5个主要属性: appName:Web浏览器的名称 appVersion:浏览器的版本号和其他版本信息 userAgent:浏览器在它的USER-AGENT HTTP标题中发送的字 ...
- CentOS7.4 + Hadoop2.9安装配置管理(分布式)
1. 规划 1.1. 机器列表 NameNode SecondaryNameNode DataNodes 192.168.1.121 192.168.1.122 192.168.1.101 192 ...
- xcrun: error: invalid active developer path (/Applications/Xcode.app/Contents/Developer)解决办法
背景 mac下卸载了xcode,使用git等命令时就提示错误.invalid active path(Applications/Xcode.app/Contents/Developer),这种情况可以 ...