LCT系列

#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;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值