[BZOJ1014][JSOI2008]火星人prefix
来源:互联网 发布:怎样投诉淘宝客服 编辑:程序博客网 时间:2024/04/28 02:00
[JSOI2008]火星人prefix
Description
火星人最近研究了一种操作:求一个字串两个后缀的公共前缀。比方说,有这样一个字符串:madamimadam,我们将这个字符串的各个字符予以标号:序号: 1 2 3 4 5 6 7 8 9 10 11 字符 m a d a m i m a d a m 现在,火星人定义了一个函数LCQ(x, y),表示:该字符串中第x个字符开始的字串,与该字符串中第y个字符开始的字串,两个字串的公共前缀的长度。比方说,LCQ(1, 7) = 5, LCQ(2, 10) = 1, LCQ(4, 7) = 0 在研究LCQ函数的过程中,火星人发现了这样的一个关联:如果把该字符串的所有后缀排好序,就可以很快地求出LCQ函数的值;同样,如果求出了LCQ函数的值,也可以很快地将该字符串的后缀排好序。 尽管火星人聪明地找到了求取LCQ函数的快速算法,但不甘心认输的地球人又给火星人出了个难题:在求取LCQ函数的同时,还可以改变字符串本身。具体地说,可以更改字符串中某一个字符的值,也可以在字符串中的某一个位置插入一个字符。地球人想考验一下,在如此复杂的问题中,火星人是否还能够做到很快地求取LCQ函数的值。
Input
第一行给出初始的字符串。第二行是一个非负整数M,表示操作的个数。接下来的M行,每行描述一个操作。操作有3种,如下所示: 1、 询问。语法:Q x y,x, y均为正整数。功能:计算LCQ(x, y) 限制:1 <= x, y <= 当前字符串长度。 2、 修改。语法:R x d,x是正整数,d是字符。功能:将字符串中第x个数修改为字符d。限制:x不超过当前字符串长度。 3、 插入:语法:I x d,x是非负整数,d是字符。功能:在字符串第x个字符之后插入字符d,如果x = 0,则在字符串开头插入。限制:x不超过当前字符串长度。
Output
对于输入文件中每一个询问操作,你都应该输出对应的答案。一个答案一行。
Sample Input
madamimadam
7
Q 1 7
Q 4 8
Q 10 11
R 3 a
Q 1 7
I 10 a
Q 2 11
Sample Output
5
1
0
2
1
HINT
数据规模:
对于100%的数据,满足:
1、 所有字符串自始至终都只有小写字母构成。
2、 M <= 150,000
3、 字符串长度L自始至终都满足L <= 100,000
4、 询问操作的个数不超过10,000个。
对于第1,2个数据,字符串长度自始至终都不超过1,000
对于第3,4,5个数据,没有插入操作。
Source
JSOI
Solution
-Wall -Shadow -Extra
Code
#include <bits/stdc++.h>using namespace std;typedef long long ll;typedef unsigned int UI;#define rep(i, l, r) for (int i = (l); i <= (r); i++)#define per(i, r, l) for (int i = (r); i >= (l); i--)#define REP(i, n) for (int i = 0; i < (n); i++)#define PER(i, n) for (int i = (n)-1; i >= 0; i--)#define stack _stackconst int N = 111111;const int INF = ~0U>>2;const UI SEED = 131;template<typename T> inline void read(T &x){ x = 0; T f = 1; char ch = getchar(); while (!isdigit(ch)) {if (ch == '-') f = -1; ch = getchar();} while (isdigit(ch)) {x = x * 10 + ch - '0'; ch = getchar();} x *= f;}template<typename T> inline void write(T &x){ static T a[20]; int ptr = 0; if (!x) {puts("0"); return;} if (x < 0){putchar('-'); x = -x;} while (x) {a[ptr++] = x % 10; x /= 10;} per(i, ptr-1, 0) putchar('0' + a[i]); putchar('\n');}char str[N];UI P[N];struct node{ node *ch[2], *p; UI key; int sz, val; bool d(){return this == p->ch[1];} void sc(node *_c, int _d) {ch[_d] = _c; _c->p = this;}}*Null, *root;inline void push_up(node *t){ t->sz = t->ch[0]->sz + t->ch[1]->sz + 1; UI ret = t->ch[0]->key; ret = ret * SEED + t->val; ret *= P[t->ch[1]->sz]; ret += t->ch[1]->key; t->key = ret;}node mem[N];node *stack[N]; int top;inline void init_memory() {REP(i, N) stack[i] = mem + i; top = N;}inline node *new_node() {return stack[--top];}inline node *new_node(int v){ node *ret = new_node(); ret->val = ret->key = v; ret->sz = 0; ret->ch[0] = ret->ch[1] = ret->p = Null; return ret;}inline void init_null(){ Null = new_node(0); Null->sz = Null->key = Null->val = 0; Null->p = Null->ch[0] = Null->ch[1] = Null;}inline void rot(node *t){ node *p = t->p; int d = t->d(); p->sc(t->ch[!d], d); if (p-p==Null) t->p == Null; else p->p->sc(t, p->d()); t->sc(p, !d); push_up(p); push_up(t); if (p == root) root = t;}inline void splay(node *t, node *fa){ for(; t->p != fa;){ if (t->p->p == fa) rot(t); else t->d() == t->p->d()?(rot(t->p), rot(t)):(rot(t), rot(t)); } push_up(t);}inline node *find(int k){ for (node *t = root; ;){ int cnt = t->ch[0]->sz; if (cnt == k) return t; t = t->ch[k > cnt]; if (k > cnt) k -= cnt+1; }}node *&getseq(int l, int r){ node *L = find(l); splay(L, Null); node *R = find(r); splay(R, root); return root->ch[1]->ch[0];}inline void Insert(int v, int pos){ node *t = new_node(v); getseq(pos, pos + 1); root->ch[1]->sc(t, 0); splay(t, Null);}inline void Replace(int v, int pos){ node *t = getseq(pos-1, pos+1); t->val = t->key = v; splay(t, Null); }inline void build(){ init_memory(); init_null(); root = new_node(0); node *end = new_node(0); root->sc(end, 1); splay(end, Null);}inline UI Cal(int l, int r){ node *t = getseq(l-1, r+1); return t->key; }inline void Query(int l, int r){ int ret = 0; int n = root->sz-2; for(int i = (1<<18); i > 0; i >>= 1){ if(l+i-1<=n && r+i-1<=n && Cal(l, l+i-1) == Cal(r, r+i-1)){ ret += i; l += i; r += i; } } write(ret);}int main(){ scanf("%s", str); int n = strlen(str); P[0] = 1; rep(i, 1, N) P[i] = P[i-1] * SEED; build(); REP(i, n) Insert(str[i], i); int m; read(m); while (m--){ char opt[20]; int pos, v; char ch; scanf("%s", opt); switch (opt[0]){ case 'I': read(pos); ch = getchar(); Insert(ch, pos); break; case 'Q': read(pos); read(v); Query(pos, v); break; case 'R': read(pos); ch = getchar(); Replace(ch, pos); break; } } return 0; }
- 【BZOJ1014】[JSOI2008]火星人prefix
- [BZOJ1014] [JSOI2008]火星人prefix
- bzoj1014 [JSOI2008]火星人prefix
- bzoj1014: [JSOI2008]火星人prefix
- [BZOJ1014][JSOI2008]火星人prefix
- 【JSOI2008】【BZOJ1014】火星人prefix
- [BZOJ1014] [JSOI2008]火星人prefix
- bzoj1014: [JSOI2008]火星人prefix
- 【BZOJ1014】【JSOI2008】火星人prefix
- [bzoj1014][JSOI2008]火星人prefix
- bzoj1014: [JSOI2008]火星人prefix
- bzoj1014: [JSOI2008]火星人prefix
- 【BZOJ1014】[JSOI2008]火星人prefix
- [BZOJ1014][JSOI2008]火星人prefix
- bzoj1014: [JSOI2008]火星人prefix
- 【bzoj1014】[JSOI2008]火星人prefix
- BZOJ1014: [JSOI2008]火星人prefix
- [bzoj1014]:[JSOI2008]火星人prefix
- 记录驾校考点(20160426拿到驾照,完结)
- ASCLL码表
- 修改eclipse对jsp文件sorce format长度
- java自行实现单线程定时器
- crazyflie2.0融合磁力计问题
- [BZOJ1014][JSOI2008]火星人prefix
- xcode7制作framework(包含加入xib,资源文件等)
- 杭电acm 4561(连续最大积的相关题目)
- hdoj--1408--盐水的故事(技巧)
- xml文件解析类及Android项目中常用到的两种获取xml文件方式
- Linux命令简介—pwd
- java classloader
- Oracle 中使用fetch bulk collect into 批量效率的读取游标数据
- 腾讯Bugly干货分享:Android应用性能评测调优