ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

[SHOI2014]三叉神经树

2021-05-11 21:33:47  阅读:159  来源: 互联网

标签:int void up 三叉神经 m1 m2 SHOI2014 inline


这是一道不那么\(native\)的\(LCT\)题,当然可用树剖做,不过在学\(LCT\),自然拿\(LCT\)做。
先考虑分析一些性质。
Q:暴力我们要怎么做?
A:建出树来,从这个节点,一直往上跑,直到对父亲节点没有贡献。
Q:什么时候对父亲节点有贡献呢。
A:当父亲节点只有1个1时,你从0变成了1,当父亲节点只有2个1时,你从1变成了2。
那么我们考虑记一个v:这个节点在树中有多少个1儿子。
那么当一个点从0 -> 1,我们先把他的父亲\(access\),然后\(spaly\),记m1,m2为splay中儿子中在原树中最深的不为1,不为2的节点,我们考虑把这个点往下的v加一个\(1\),然后把m1,m2交换(这个感性理解,你发现肯定是这样的)。(注意定义是不为1,不为2。)
于是1->0是一样的操作。
我们直接用\(LCT\)做。
有不清楚的看代码:

[SHOI2014]三叉神经树
#include<iostream>
#include<cstdio>
#define ll long long
#define N 500005

int f[3 * N],c[3 * N][2],v[3 * N],m1[3 * N],m2[3 * N],ans[3 * N],t[3 * N];

#define l(x) c[x][0]
#define r(x) c[x][1]

inline bool nroot(int x){return l(f[x]) == x || r(f[x]) == x;}

inline void up (int x){
	m1[x] = m1[r(x)];
	m2[x] = m2[r(x)];
	if(!m1[x]){
		if(v[x] != 1)
		m1[x] = x;
		else
		m1[x] = m1[l(x)];
	}
	if(!m2[x]){
		if(v[x] != 2)
		m2[x] = x;
		else
		m2[x] = m2[l(x)];
	}
}


inline void dn(int x,int y){v[x] = v[x] + y;ans[x] = v[x] > 1;std::swap(m1[x],m2[x]);t[x] += y;} 
 
inline void pushdown(int x){
if(t[x]){
	dn(l(x),t[x]);
	dn(r(x),t[x]);
	t[x] = 0;
}}

ll st[N];

inline void rotate(int x){
	int y = f[x],z = f[y],k = r(y) == x,w = c[x][!k];
	if(nroot(y))c[z][r(z) == y] = x;c[x][!k] = y;c[y][k] = w;
	if(w)f[w] = y;f[y] = x;f[x] = z;
	up(y),up(x);
}

inline void splay(int x){
	ll y = x,z = 0;
	st[++z] = y;
	while(nroot(y))st[++z] = y = f[y];
	while(z)pushdown(st[z -- ]);
	while(nroot(x)){
		ll y = f[x],z = f[y];
		if(nroot(y))
		rotate((l(z) == y) ^ (l(y) == x) ? x : y);
		rotate(x);
	}  
	up(x);
}

inline void access(int x){
	for(int y = 0;x;x = f[y = x]){
		splay(x),r(x) = y,up(x);
	}
}

struct P{int to,next;}e[N * 6]; 

ll head[3 * N],cnt;

inline void add(int x,int y){
	e[++cnt].to = y;
	e[cnt].next = head[x];
	head[x] = cnt; 
}

ll n;

inline void dfs(int u,int fa){
	v[u] = 0;
	for(int i = head[u];i;i = e[i].next){
		int vi = e[i].to;
		if(vi == fa)
		continue;
		dfs(vi,u);
		v[u] += ans[vi];
	}
	if(u <= n)ans[u] = v[u] > 1;
}

int main(){
	scanf("%lld",&n);
	for(int i = 1;i <= n;++i){
		for(int j = 1;j <= 3;++j){
			ll x;
			scanf("%lld",&x);
			f[x] = i;
			add(i,x);
			add(x,i);
		} 
	}
	for(int i = n + 1;i <= n * 3 + 1;++i)
	scanf("%lld",&ans[i]);
	dfs(1,0);
	ll m;
	ll art = ans[1];
	scanf("%lld",&m);
	while(m -- ){
		ll now;
		scanf("%lld",&now);
		ll x = f[now];
		ll tag = ans[now] ? -1 : 1;
		access(x),splay(x);
		ll w = 0;
		w = (ans[now] ? m2[x] : m1[x]);
		if(w){
			splay(w);
			dn(r(w),tag),up(r(w));
			v[w] += tag;ans[w] = v[w] > 1;up(w); 
		}
		else{
			art ^= 1,dn(x,tag),up(x);
		}
		ans[now] ^= 1;
		std::cout<<art<<std::endl;
	}
}

标签:int,void,up,三叉神经,m1,m2,SHOI2014,inline
来源: https://www.cnblogs.com/dixiao/p/14757360.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有