题意:给一个字符串,三种操作,末尾插入一个字符,弹出末尾的字符,查询区间内一个给定字符串出现了多少次。
卡常神题。。500万的数据规模什么鬼。。
假如没有区间限制,就是后缀平衡树的裸题。查询一个字符串s出现了多少次,就是在后缀平衡树上找出
由于替罪羊的删除不是很方便,这里可以用treap,删除一个节点的时候直接重构这个节点所在的子树。以前重构操作都是直接写在rotate里面的,用起来非常方便。这里为了常数问题,可以像替罪羊那样记录一个最高的需要重构的点重构即可。
考试的时候有人用分块过了的,就是将询问串分成比格和思茅。以后考试的时候如果不敢写正解的话可以试试这种分块来骗分。
#include
#include
#include
#include
#include
#include
#define rep(i,a,b) for(int i=a;i<=b;++i)
#define erp(i,a,b) for(int i=a;i>=b;--i)
#define ALL(x) (x).begin(), (x).end()
#define Exist(x,y) ((x) ? (x) : (y))
#define pb push_back
#define LL long long
using namespace std;
const int MAXN = 500005;
const LL INF = 1ll<<61;
inline int ran() {
static int a=5116213;
return a=(a*1237+521)&0x7fffffff;
}
inline int get(char*s)
{
int len = 0, c;
do c=getchar(); while(!isalpha(c));
do s[len++]=c, c=getchar(); while(isalpha(c));
return s[len] = '\0', len;
}
inline int get(int&r)
{
char c; r=0;
do c=getchar(); while(c<'0'||c>'9');
do r=r*10+c-'0',c=getchar(); while(c>='0'&&c<='9');
}
inline int cid(char x) { return x<='Z'?x-'A'+26:x-'a'; }
inline char wrd(int x) { return x<26?x+'a':x-26+'A'; }
char str[MAXN], s[MAXN*10];
int Q, lens, ans;
#define lch(x) (x->ch[0])
#define rch(x) (x->ch[1])
#define nodepos(x) ((x)-nds)
#define siz(x) (x?x->sz:0)
struct Node {
Node *ch[2], *nxt;
int fix, c;
LL key;
vector vec;
} nds[MAXN], *ncnt = nds, *rt;
inline int calc(vector&v, int l, int r)
{
return upper_bound(ALL(v), r)-lower_bound(ALL(v), l);
}
inline void rotate(Node*&x, int d)
{
Node*y = x->ch[!d];
x->ch[!d] = y->ch[d];
y->ch[d] = x;
x = y;
}
inline int cmp(Node*x, Node*y)
{
if (x->c^y->c) return x->c < y->c;
return x->nxt->key < y->nxt->key;
}
inline void upvec(Node*x)
{
x->vec.clear();
if (lch(x)&&rch(x))
{
x->vec.resize(lch(x)->vec.size()+rch(x)->vec.size());
merge(ALL(lch(x)->vec), ALL(rch(x)->vec), x->vec.begin());
}
else if (lch(x)&&!rch(x)) x->vec = lch(x)->vec;
else if (rch(x)&&!lch(x)) x->vec = rch(x)->vec;
int t = nodepos(x);
x->vec.insert(upper_bound(ALL(x->vec), t), t);
}
void rebuild(Node*x, LL l, LL r)
{
if (!x) return;
LL mid = l+r>>1;
x->key = l+r;
rebuild(lch(x), l, mid);
rebuild(rch(x), mid, r);
upvec(x);
}
int rotflag;
void ins(Node*&x, LL l, LL r)
{
if (!x) { (x=ncnt)->key = l+r; return; }
int d = cmp(x, ncnt); //d=0表示插入节点比当前节点小
LL mid = l+r>>1;
if (!d) ins(lch(x), l, mid);
else ins(rch(x), mid, r);
if (x->ch[d]->fix > x->fix)
rotate(x, !d);
else
{
if (rotflag)
{
if (!d) rebuild(lch(x), l, mid);
else rebuild(rch(x), mid, r);
rotflag = 0;
}
x->vec.pb(nodepos(ncnt));
}
if (x==rt&&rotflag)
rebuild(x, l, r);
}
void del(Node*&x, LL l, LL r)
{
LL mid = l+r>>1;
if (x==ncnt)
{
bool firstmeet = rotflag;
rotflag = 0;
if (!lch(x) || !rch(x))
{
x = Exist(lch(x), rch(x));
if (!x) return;
}
else {
if (lch(x)->fix>rch(x)->fix)
rotate(x, 1), del(rch(x), mid, r);
else
rotate(x, 0), del(lch(x), l, mid);
}
if (firstmeet) rebuild(x, l, r);
}
else
{
x->vec.pop_back();
if (ncnt->key < x->key) del(lch(x), l, mid);
else del(rch(x), mid, r);
}
}
inline void extend(int c)
{
str[++lens] = c;
(++ncnt)->c=c;
ncnt->fix=ran(), ncnt->vec.clear();
lch(ncnt)=rch(ncnt)=0x0, ncnt->nxt=ncnt-1;
rotflag = 1, ins(rt, 1, INF);
}
inline void popchar()
{
rotflag = 1, del(rt, 1, INF);
ncnt --, lens --;
}
int revlcp(Node*x, char*s, int len)
{
int p = nodepos(x), l = 0;
while (lr||!x) return 0;
int sm = revlcp(x, s, len), d, p=nodepos(x); //d表示x是否比s小
if (sm==len) d = pstr[p-sm];
int flag = p>=l&&p<=r&&d;
if (!d) return calcless(lch(x), s, len, l, r);
int lef = lch(x)?calc(lch(x)->vec, l, r):0;
return lef + flag + calcless(rch(x), s, len, l, r);
}
int quary(int l, int r, char*s, int len)
{
int L=l+len-1, R=r;
int sum1 = calcless(rt, s, len, L, R);
len++;
erp(i, len, 2) s[i] = s[i-1];
s[1] = 'z'+1;
int sum2 = calcless(rt, s, len, L, R);
return sum2 - sum1;
}
void decode(char*s, int len)
{
rep(i, 1, len) s[i] = wrd((cid(s[i])+ans)%52);
}
int main()
{
int len = get(s+1);
rep(i,1,len) extend(s[i]);
get(Q);
for (int op, l, r; Q--; )
{
get(op);
if (op==1)
{
get(s+1);
decode(s,1);
extend(s[1]);
}
else if (op==2) popchar();
else {
get(l), get(r);
l^=ans, r^=ans;
len = get(s+1);
decode(s,len);
ans = quary(l, r, s, len);
printf("%d\n", ans);
}
}
return 0;
}