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 因此...