#1:[HNOI2010]弹飞绵羊
这道题是YM了Seter的模板以后过的
后来YM了wangxz神犇的姿势
题意:换父亲,询问点到根路径上的节点数
新技能:用fread刷rank
Code:
#include <cstdio>
using namespace std;
#define N 200001
struct Splay_Tree
{
Splay_Tree *F, *Ls, *Rs;
int Size;
}T[N], Empty;
inline void Init(Splay_Tree *x)
{
x->F = x->Ls = x->Rs = &Empty;
x->Size = 1;
}
inline Splay_Tree *Update(Splay_Tree *x)
{
x->Size = 1 + x->Ls->Size + x->Rs->Size;
return x;
}
inline Splay_Tree *f(Splay_Tree *x)
{
if (x->F != &Empty)
return (x->F->Ls == x || x->F->Rs == x) ? x->F : &Empty;
return x->F;
}
inline Splay_Tree *rot(Splay_Tree * x)
{
Splay_Tree *fx = f(x), *ffx = f(fx);
bool c = fx->Rs == x, fc = ffx->Rs == fx;
if (fx != &Empty)
{
x->F = fx->F;
if (c)
{
fx->Rs = x->Ls;
if (fx->Rs != &Empty)
fx->Rs->F = fx;
Update((fx->F = x)->Ls = fx);
}
else
{
fx->Ls = x->Rs;
if (fx->Ls != &Empty)
fx->Ls->F = fx;
Update((fx->F = x)->Rs = fx);
}
if (ffx != &Empty)
{
if (fc)
ffx->Rs = x;
else
ffx->Ls = x;
}
}
return x;
}
inline Splay_Tree *Splay(Splay_Tree *x, Splay_Tree *p)
{
Splay_Tree *fx, *ffx;
if (x == &Empty)return x;
for(;(fx = f(x)) != p;rot(x))
if((ffx = f(fx)) != p)
rot((ffx->Rs == fx) == (fx->Rs == x) ? fx : x);
return Update(x);
}
inline Splay_Tree *Access(Splay_Tree *v)//½«vµ½×ܸùÁ¬³ÉÒ»¿ÃSplay
{
Splay_Tree *t = &Empty, *y = v;
while (1)
{
Splay(v, &Empty);
v->Rs = t;
if (t != &Empty)f(t);
if (v->F == &Empty)break;
Update(v);
t = v;
v = t->F;
}
Splay(y, &Empty);
return y;
}
char str[1500000], *c = str;
inline void read(int &x)
{
int opt(1);
for (;*c > '9' || *c < '0';c++)
if (*c == '-')
opt = -1;
for (x = 0;*c >= '0' && *c <= '9'; ++c)
x = (x << 3) + (x << 1) + *c - '0';
x *= opt;
}
int n, m;
int main()
{
int i, j, k;
fread(str, 1, 1500000, stdin);
Empty.F = Empty.Ls = Empty.Rs = 0;
read(n);
for (i = 0;i < n; ++i)
Init(&T[i]);
for (i = 0;i < n; ++i)
{
read(k);
if (i+k < n)
T[i].F = (T+i+k);
else
T[i].F = &Empty;
}
read(m);
while (m--)
{
if (*++c == '1')
{
*c++;
read(j);
printf("%d\n", Access(T+j)->Ls->Size+1);
}
else
if (*c == '2')
{
*c++;
read(j), read(k);
Access(T+j)->Ls->F = &Empty;
f(T[j].Ls);
T[j].Ls = &Empty;
Update(&T[j])->F = j + k >= n ? &Empty : T+j+k;
}
}
}
#2:[ZJOI2008]树的统计
ZJ爷的标程是LCT
然后写LCT被神犇D:这题写什么LCT
题意:一棵树,点带权,修改点权,询问两点之间路径上最大权值或权值和
可用多种姿势
Update写错一次,Pushdown少加了几个地方......why am I so weak.
Code:
#include <cstdio>
#include <bitset>
#include <queue>
using namespace std;
#define N 30001
bitset<N> vis;
queue<int> Q;
struct node
{
node *F, *Ls, *Rs;
int Key, Sum, Reverse, Max;
inline node *Update()
{
Sum = Key + Ls->Sum + Rs->Sum;
Max = max(Key, max(Ls->Max, Rs->Max));
return this;
}
}T[N], Empty;
struct E
{
int to, next;
}G[N<<1];
int n, m, cnt, point[N];
inline void add(int u, int v)
{
cnt++, G[cnt] = (E){v, point[u]}, point[u] = cnt;
cnt++, G[cnt] = (E){u, point[v]}, point[v] = cnt;
}
char str[5000000], *c = str;
inline void Init(node *now, int x)
{
now->F = now->Ls = now->Rs = &Empty;
now->Sum = now->Max = now->Key = x;
}
inline node *f(node *now)
{
if (now->F == &Empty)return now->F;
if (now->F->Ls == now || now->F->Rs == now)return now->F;
return &Empty;
}
inline void Pushdown(node *now)
{
if (now->Reverse)
{
now->Reverse ^= 1;
swap(now->Ls, now->Rs);
if (now->Ls != &Empty)
now->Ls->Reverse ^= 1;
if (now->Rs != &Empty)
now->Rs->Reverse ^= 1;
}
}
inline node *rot(node *now)
{
node *fx = f(now), *ffx = f(fx);
if (ffx != &Empty)
Pushdown(ffx);
if (fx != &Empty)
{
Pushdown(fx);
Pushdown(now);
now->F = fx->F;
if (now == fx->Rs)
{
fx->Rs = now->Ls;
if (fx->Rs != &Empty)
fx->Rs->F = fx;
((fx->F = now)->Ls = fx)->Update();
}
else
{
fx->Ls = now->Rs;
if (fx->Ls != &Empty)
fx->Ls->F = fx;
((fx->F = now)->Rs = fx)->Update();
}
now->Update();
if (ffx != &Empty)
{
if (fx == ffx->Rs)
ffx->Rs = now;
else
ffx->Ls = now;
ffx->Update();
}
}
return now;
}
inline node *Splay(node *now, node *tar)
{
node *fx, *ffx;
Pushdown(now);
for (;(fx = f(now)) != tar;rot(now))
if ((ffx = f(fx)) != tar)
rot((ffx->Rs == fx) == (fx->Rs == now) ? fx : now);
return now->Update();
}
inline node *Access(node *now)
{
node *t = &Empty, *y = now;
while (now != &Empty)
{
Splay(now, &Empty)->Rs = t;
now->Update();
now = (t = now)->F;
}
return t;
}
inline void Evert(node *now)
{
Access(now)->Reverse ^= 1;
Splay(now, &Empty);
}
inline node *Query(int l, int r)
{
Evert(T+l);
Access(T+r);
Splay(T+r, &Empty);
return T+r;
}
inline void read(int &x)
{
int opt(1);
for (;*c > '9' || *c < '0'; ++c)
if (*c == '-')
opt = -1;
for (x = 0;*c >= '0' && *c <= '9'; ++c)
x = (x << 3) + (x << 1) + *c - '0';
x *= opt;
}
int main()
{
// freopen("a.in", "r", stdin);
int i, j, k;
Empty.F = Empty.Ls = Empty.Rs = &Empty;
Empty.Max = -30001;
fread(str, 1, 5000000, stdin);
read(n);
for (i = 1;i < n; ++i)
{
read(j), read(k);
add(j, k);
}
for (i = 1;i <= n; ++i)
{
read(j);
Init(T+i, j);
}
Q.push(1);
vis[1] = 1;
while (!Q.empty())
{
j = Q.front();
Q.pop();
for (i = point[j];i;i = G[i].next)
{
k = G[i].to;
if (!vis[k])
{
vis[k] = 1;
T[k].F = T+j;
Q.push(k);
}
}
}
read(m);
while (m--)
{
if (*++c == 'C')
{
read(i), read(j);
T[i].Key = j;
(T+i)->Update();
Access(T+i);
}
else
if (*c == 'Q')
{
if (*++c == 'M')
{
read(i), read(j);
printf("%d\n", i == j ? T[i].Key : Query(i, j)->Max);
}
else
if (*c == 'S')
{
read(i), read(j);
printf("%d\n", i == j ? T[i].Key : Query(i, j)->Sum);
}
}
}
return 0;
}
两节课重写了一遍,换了一种姿势,快了不少
Code:
#include <cstdio>
#include <queue>
#include <bitset>
using namespace std;
#define N 30001
queue<int> Q;
bitset<N> vis;
struct node
{
node *F, *S[2];
int Key, Max, Sum, Reverse;
inline void Init(int x)
{
Key = Max = Sum = x;
Reverse = 0;
F = S[0] = S[1] = 0;
}
inline void Pushdown()
{
if (Reverse)
{
Reverse ^= 1;
swap(S[0], S[1]);
if (S[0])S[0]->Reverse ^= 1;
if (S[1])S[1]->Reverse ^= 1;
}
}
inline node *Update()
{
Sum = Max = Key;
if (S[0])Sum += S[0]->Sum, Max = max(Max, S[0]->Max);
if (S[1])Sum += S[1]->Sum, Max = max(Max, S[1]->Max);
return this;
}
inline node *f()
{
if (!F)return 0;
if (F->S[0] == this || F->S[1] == this)return F;
return 0;
}
inline node *rot()
{
node *fx = f(), *ffx = fx ? fx->f() : 0;
if (ffx)ffx->Pushdown();
if (fx)
{
fx->Pushdown();
Pushdown();
bool c = (this == (fx ? fx->S[1] : 0));
F = fx->F;
fx->F = this;
fx->S[c] = S[!c];
if (S[!c])S[!c]->F = fx;
fx->Update();
S[!c] = fx;
Update();
}
if (ffx)
{
bool fc = (fx == (ffx ? ffx->S[1] : 0));
ffx->S[fc] = this;
}
return this;
}
inline node *Splay()
{
Pushdown();
node *fx, *ffx;
for (;fx = f();rot())
if (ffx)(this == fx->S[1] && fx == ffx->S[1]) ? fx->rot() : rot();
return this;
}
inline node *Access()
{
node *p = this, *v = 0;
while (p)
{
p->Splay()->S[1] = v;
p->Update();
p = (v = p)->F;
}
return v;
}
inline void Evert()
{
Access()->Reverse ^= 1;
Splay();
}
}T[N];
inline node *Query(int u, int v)
{
(T+u)->Evert();
(T+v)->Access();
(T+v)->Splay();
return T+v;
}
struct E
{
int to, next;
}G[N<<1];
char str[10000000], *c = str;
inline void read(int &x)
{
int opt(1);
for (;*c > '9' || *c < '0'; ++c)
if (*c == '-')
opt = -1;
for (x = 0;*c >= '0' && *c <= '9'; ++c)
x = (x << 3) + (x << 1) + *c - '0';
x *= opt;
}
int n, m, i, j, k, cnt, point[N];
inline void add(int u, int v)
{
cnt++, G[cnt] = (E){v, point[u]}, point[u] = cnt;
cnt++, G[cnt] = (E){u, point[v]}, point[v] = cnt;
}
int main()
{
freopen("a.in", "r", stdin);
freopen("a.out", "w", stdout);
fread(str, 1, 5000000, stdin);
read(n);
for (i = 1;i < n; ++i)
{
read(j), read(k);
add(j, k);
}
for (i = 1;i <= n; ++i)
{
read(j);
T[i].Init(j);
}
Q.push(1);
vis[1] = 1;
while (!Q.empty())
{
j = Q.front();
Q.pop();
for (i = point[j];i;i = G[i].next)
{
k = G[i].to;
if (!vis[k])
{
vis[k] = 1;
T[k].F = &T[j];
Q.push(k);
}
}
}
read(m);
while (m--)
{
if (*++c == 'C')
{
read(i), read(j);
T[i].Key = j;
T[i].Update();
T[i].Access();
}
else
{
if (*++c == 'M')
{
read(i), read(j);
printf("%d\n", i == j ? T[i].Key : Query(i, j)->Max);
}
else
{
read(i), read(j);
printf("%d\n", i == j ? T[i].Key : Query(i, j)->Sum);
}
}
}
return 0;
}