1. 程式人生 > >[Luogu P4332] [BZOJ 3553] [SHOI2014]三叉神經樹

[Luogu P4332] [BZOJ 3553] [SHOI2014]三叉神經樹

洛谷傳送門

BZOJ傳送門

題目描述

計算神經學作為新興的交叉學科近些年來一直是學術界的熱點。一種叫做SHOI 的神經組織因為其和近日發現的化合物 SHTSC 的密切聯絡引起了人們的極大關注。

SHOI 組織由若干個 SHOI 細胞構成,SHOI 細胞之間形成嚴密的樹形結構。每個 SHOI 細胞都有且只有一個輸出端,被稱為軸突,除了一個特殊的、被稱為根細胞的 SHOI 細胞的輸出作為整個組織的輸出以外,其餘細胞的軸突均連向其上級 SHOI 細胞;並且有且只有三個接收端,被稱為樹突,從其下級細胞或者其它神經組織那裡接收資訊。SHOI 細胞的訊號機制較為簡單,僅有 0

0 1 1 兩種。每個 SHOI 細胞根據三個輸入端中 0 0 1
1
訊號的多寡輸出較多的那一種。

現在給出了一段 SHOI 組織的資訊,以及外部神經組織的輸入變化情況。請你模擬 SHOI 組織的輸出結果。

輸入輸出格式

輸入格式:

輸入的第一行包含一個整數 n n 。表示 SHOI 組織的總細胞個數。SHOI 細胞由 1

n 1\sim n 編號,編號為 1 1 的是根細胞。

從第二行開始的 n n 行,每行三個整數 x 1 , x 2 , x 3 x_1, x_2, x_3 ,分別表示編號為 1 n 1\sim n 的 SHOI 細胞的樹突連線。 1 < x i n 1 < x_i \leq n 表示連向編號為 x i x_i 的細胞的軸突, n < x i 3 n + 1 n < x_i \leq 3n+1 表示連向編號為 x i x_i 的外界輸入。輸入資料保證給出的 SHOI 組織是合法的,且所有的 x i x_i 兩兩不同。

接下來一行包含 2 n + 1 2n+1 0 / 1 0/1 的整數,表示初始時的外界輸入。

n + 3 n+3 行有一個整數 q q ,表示總運算元。

之後 q q 行每行一個整數 x x ,表示編號為 x x 的外界輸入發生了變化。

輸出格式:

輸出 q q 行,每行一個整數,對應第 i i 次外界輸入變化後的根細胞的輸出。

輸入輸出樣例

輸入樣例#1:

3
2 3 4
5 6 7
8 9 10
0 0 0 0 1 1 1
5
4
4
5
6
8

輸出樣例#1:

1
0
0
1
1

說明

對於 10 % 10 \% 的資料, n 1000 , q 1000 n \leq 1000, q \leq 1000

對於 30 % 30 \% 的資料, n 100000 , q 100000 n \leq 100000, q \leq 100000

對於 100 % 100 \% 的資料, n 500000 , q 500000 n \leq 500000, q \leq 500000

解題分析

可以發現, 每次更改最底層的結果會改變自底向上的一條鏈上連續 0 / 1 0/1 的結果, 更具體地說, 設 v a l [ i ] val[i] i i 號節點的權值, 那麼改變的是自底部開始的 v a l = 1 / 2 val=1/2 的一部分。

那麼我們直接用 L C T LCT 維護鏈上從下向上第一個權值不為 1 / 2 1/2 的位置, 在修改的時候直接 a c c e s s access 後找到這個位置, 再區間打一個修改 t a g tag 就好了。

注意如果到根節點都沒有要求的點, 直接修改答案, 在根節點上打 t a g tag

程式碼如下:

#include <cstdio>
#include <cstring>
#include <cmath>
#include <cctype>
#include <cstdlib>
#include <algorithm>
#include <queue>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 500500
template <class T>
IN void in(T &x)
{
	x = 0; R char c = gc;
	for (; !isdigit(c); c = gc);
	for (;  isdigit(c); c = gc)
	x = (x << 1) + (x << 3) + c - 48;
}
std::queue <int> q;
int n, m, top;
int sta[MX], deg[MX];
struct Node {int son[2], fat, p1, p2, val, tag;} tree[MX << 2];
namespace LCT
{
	#define ls tree[now].son[0]
	#define rs tree[now].son[1]
	#define dad tree[now].fat
	IN bool get(R int now) {return tree[dad].son[1] == now;}
	IN bool nroot(R int now) {return tree[dad].son[1] == now || tree[dad].son[0] == now;}
	IN void pushup(R int now)
	{
		if (!tree[rs].p1)
		{
			if (tree[now].val != 1) tree[now].p1 = now;
			else tree[now].p1 = tree[ls].p1;
		} else tree[now].p1 = tree[rs].p1;
		if (!tree[rs].p2)
		{
			if (tree[now].val != 2) tree[now].p2 = now;
			else tree[now].p2 = tree[ls].p2;
		} else tree[now].p2 = tree[rs].p2;
	}
	IN void pushtag(R int now, R int del)
	{
		tree[now].tag += del;
		tree[now].val ^= 3;
		std::swap(tree[now].p1, tree[now].p2);
	}
	IN void pushdown(R int now)
	{
		if (tree[now].tag)
		pushtag(ls, tree[now].tag), pushtag(rs, tree[now].tag), tree[now].tag = 0;
	}
	IN void rotate(R int now)
	{
		R int fa = dad, grand = tree[fa].fat;
		R bool dir = get(now);
		tree[fa].son[dir] = tree[now].son[dir ^ 1];
		tree[tree[now].son[dir ^ 1]].fat = fa;
		tree[now].fat = grand;
		if (nroot(fa)) tree[grand].son[get(fa)] = now;
		tree[now].son[dir ^ 1] = fa;
		tree[fa].fat = now;
		pushup(fa);
	}
	IN void splay(R int now)
	{
		int tmp = now, fa;
		sta[top = 1] = now;
		W (nroot(now)) sta[++top] = now = dad;
		W (top) pushdown(sta[top--]);
		now = tmp;
		W (nroot(now))
		{
			fa = dad;
			if (nroot(fa)) rotate(get(fa) == get(now) ? fa : now);
			rotate(now);
		}
		pushup(now);
	}
	IN void access(R int now)
	{
		for (R int x = 0; now; x = now, now = dad)
		splay(now), rs = x, pushup(now);
	}
	#undef ls
	#undef rs
	#undef dad
}
int main(void)
{
	using namespace LCT;
	in(n); int foo, bar, typ, ans, bd = 3 * n + 1;
	for (R int i = 1; i <= n; ++i)
	{
		deg[i] = 3;
		for (R int j = 1; j <= 3; ++j) in(foo), tree[foo].fat = i;
	}
	deg[0] = 999;
	for (R int i = n + 1; i <= bd; ++i) in(tree[i].val), tree[i].val <<= 1, q.push(i);
	W (!q.empty())
	{
		foo = q.front(); q.pop();
		tree[tree[foo].fat].val += tree[foo].val >> 1;
		--deg[tree[foo].fat];
		if (