SHOI2014 三叉神經樹 題解

2022-09-22 04:51:12 字數 1803 閱讀 7856

lct

一顆節點數為 \(3n+1\) 的樹,編號在 \(1 \dots n\) 的節點有且僅有三個兒子。

其餘點沒有兒子。所有節點值只可能為 \(0\) 或 $ 1$,編號在 \(n + 1 \dots 3n\) 的節點的值由輸入確定,編號在 $ 1 \to n$ 的節點的值為三個兒子中值數量更多的那種。

\(m\) 次操作,每次會改變乙個 \(n + 1\dots 3n\) 的節點的值,請每次操作結束後輸出根節點的值

\(n,m\le 5\times 10^5\)

設 \(sum\) 表示乙個節點三個兒子的權值和

我們可以發現這樣乙個性質,我們每次修改乙個葉子的權值的時候,只會影響到從葉子向上的一條鏈,這條鏈不一定到根

比如我們把乙個 \(0\) 改成 \(1\) ,那麼對應有影響的只有從葉子的父親開始 \(sum=1\) 的乙個連續的鏈

對應的,我們將 \(1\) 改成 \(0\) ,只會是一條鏈上的所有的 \(sum-1\)

考慮 lct。

現在的問題變成了如何找到這兩個點,即最深的 \(sum\neq 1\) 和 \(sum\neq 2\) 的點,找到後,只需要把這個點 splay 上去後將他的右子樹整體打乙個 tag 即可

不妨直接在每乙個節點上維護 \(neq[1/2]\) 表示子樹中(鏈)最深的不為 \(1/2\) 的位置,\(pushup\) 函式大致長這樣:(跟 flashhu 學的壓行)

void pushup(int rt)
這樣的話我們的複雜度就是 \(o(n\log n)\) ,細節在**中

#include#define ls t[rt].ch[0]

#define rs t[rt].ch[1]

#define min(a,b) ((a)<(b)?(a):(b))

#define max(a,b) ((a)>(b)?(a):(b))

#define swap(x,y) x^=y^=x^=y

using namespace std;

const int n = 2e6+5;

const int inf = 1e9;

char buf[1<<23],*p1=buf,*p2=buf;

#define getchar() (p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?eof:*p1++)

int read()

while(isdigit(ch))s=s*10+(ch^48),ch=getchar();

return s*w;

}struct treet[n];

int stk[n],top;

void pushup(int rt)

void add(int rt,int v)

void pushdown(int rt)

bool identity(int rt)

bool check(int rt)

void rotate(int rt)

void splay(int rt)

}void access(int rt)

vectoredge[n];

int n,m,ans;

void dfs(int u,int fath)

signed main()else ans^=1,add(f,tg),pushup(f);//否則直接修改整條鏈

t[pos].val^=1;

printf("%d\n",ans);

}return 0;

}

SHOI2014 三叉神經樹

給你一顆由 n 個非葉子結點和 2n 1 個葉子結點構成的三叉樹,每個結點兒子個數為 0 3 每個葉子結點有乙個輸出 0 或 1 每個非葉子結點的輸出為自己的葉子結點中較多的那一種狀態。有 q 次修改操作,每次修改乙個葉子結點的輸出,求每次修改後根結點的輸出。n leq 5 times 10 5,q...

SHOI2014 三叉神經樹

題目描述 計算神經學作為新興的交叉學科近些年來一直是學術界的熱點。一種叫做shoi 的神經組織因為其和近日發現的化合物 shtsc 的密切聯絡引起了人們的極大關注。shoi 組織由若干個 shoi 細胞構成,shoi 細胞之間形成嚴密的樹形結構。每個 shoi 細胞都有且只有乙個輸出端,被稱為軸突,...

SHOI2014 三叉神經樹 LCT

題面 loj 2187 解析 顯然修改一次需要修改一條到根的鏈,維護鏈當然就想到用lct了 結果就想偏了,本來想分別維護虛子樹資訊與整棵子樹資訊,結果發現很難維護。然後去自學了一發 我們定義乙個點的點權為它的兒子節點中選 1 的個數 考慮更改乙個點的點權要麼對它上方的鏈中連續的 1 或連續 2 因此...