题目大意
给定一个序列,每个点有一个权值a[i],一只绵羊若站在点i上会被弹到第i+a[i]个点上,支持单点修改操作,求从某个点出发经过多少次会被弹飞。
题解
令每个点的父亲结点是会被弹到的结点,那询问时每个点的答案就是这个点的深度。
LCT维护size域即可
一开始以为是有向树,后来发现自己犯2了,按无向的做法就可以。
做这种题千万别手残。我因为一句x->rever()打成x->rev^=1,就有了如下结果,调了快一整天了!
Code
#include <cstdio>
#include <algorithm>
#define maxn 200005
using namespace std;
int n, m, val[maxn];
struct node
{
bool rev;
int s;
node *fa, *lc, *rc;
node() { rev = false; s = 0; fa = lc = rc = NULL; }
node(bool xrev, int xs, node *xfa, node *xlc, node *xrc)
{
rev = xrev; s = xs;
fa = xfa; lc = xlc; rc = xrc;
}
inline void update();
inline void rever();
void pushdown();
}*nil = new node(), *T[maxn], *S[maxn];
inline void node :: update()
{
s = lc -> s + rc -> s + 1;
}
inline void node :: rever()
{
rev ^= 1;
swap(lc, rc);
}
void node :: pushdown()
{
if(rev)
{
rev = false;
lc -> rever();
rc -> rever();
}
}
void zig(node *x)
{
node *y = x -> fa;
y -> lc = x -> rc;
x -> rc -> fa = y;
x -> rc = y;
x -> fa = y -> fa;
if(y == y -> fa -> lc) y -> fa -> lc = x;
else if(y == y -> fa -> rc) y -> fa -> rc = x;
y -> fa = x;
y -> update();
}
void zag(node *x)
{
node *y = x -> fa;
y -> rc = x -> lc;
x -> lc -> fa = y;
x -> lc = y;
x -> fa = y -> fa;
if(y == y -> fa -> lc) y -> fa -> lc = x;
else if(y == y -> fa -> rc) y -> fa -> rc = x;
y -> fa = x;
y -> update();
}
void splay(node *x)
{
int top = 0;
S[top++] = x;
for(node *i = x; i == i -> fa -> lc || i == i -> fa -> rc; i = i -> fa)
{
S[top++] = i -> fa;
}
while(top--) S[top] -> pushdown();
node *y = nil, *z = nil;
while(x == x -> fa -> lc || x == x -> fa -> rc)
{
y = x -> fa; z = y -> fa;
if(x == y -> lc)
{
if(y == z -> lc) zig(y);
zig(x);
}
else
{
if(y == z -> rc) zag(y);
zag(x);
}
}
x -> update();
}
inline void access(node *x)
{
for(node *y = nil; x != nil; y = x, x = x -> fa)
{
splay(x);
x -> rc = y;
x -> update();
}
}
inline void makeroot(node *x)
{
access(x); splay(x); x -> rever();
}
inline void lnk(node *x, node *y)
{
makeroot(x);
x -> fa = y;
}
inline void cut(node *x, node *y)
{
makeroot(x);
access(y); splay(y);
x -> fa = y -> lc = nil;
y -> update();
}
inline int query(node *x)
{
makeroot(T[n]);
access(x); splay(x);
return x -> lc -> s;
}
int main()
{
int opt, a, b;
scanf("%d", &n);
*nil = node(false, 0, nil, nil, nil);
for(int i = 0; i <= n; ++i) T[i] = new node(false, 1, nil, nil, nil);
for(int i = 0; i < n; ++i)
{
scanf("%d", &val[i]);
T[i] -> fa = T[min(n, i + val[i])];
}
scanf("%d", &m);
while(m--)
{
scanf("%d", &opt);
if(opt == 1)
{
scanf("%d", &a);
printf("%d\n", query(T[a]));
}
else
{
scanf("%d%d", &a, &b);
cut(T[a], T[min(n, a + val[a])]);
val[a] = b;
lnk(T[a], T[min(n, a + val[a])]);
}
}
for(int i = 0; i < n; ++i)
{
delete T[i];
T[i] = NULL;
}
delete nil;
nil = NULL;
return 0;
}
版权声明:本文为博主原创文章,未经博主允许不得转载。
原文地址:http://blog.csdn.net/t14t41t/article/details/47613631