【SPOJ】QTREE6-Query on a tree VI
阿新 • • 發佈:2018-12-11
題解
老年選手的程式碼康復計劃QAQ
這題又沒一遍A,難受
每個節點維護這個節點子樹內聯通塊的大小
維護所有節點輕兒子的\(g[u][0]\)表示所有輕兒子白色的聯通塊總數
\(g[u][1]\)表示所有輕兒子黑色聯通塊總數
更新一個點為新顏色的時候,是\(g[u][c[u] ^ 1] + 1\)再加上重兒子價值(如果修改後顏色相同
然後我們向上更新,修改到和父親節點顏色相同的最淺的節點
如果改後顏色和父親顏色不同,那麼這些點都減去原來的值
否則都加上新值
然後在經過輕邊的時候順帶維護一下\(g\)即可
對於找顏色相同的最淺節點,用線段樹維護一個區間顏色是否相同即可
程式碼
#include <bits/stdc++.h> #define fi first #define se second #define pii pair<int,int> #define pdi pair<db,int> #define mp make_pair #define pb push_back #define enter putchar('\n') #define space putchar(' ') #define eps 1e-8 #define mo 974711 #define MAXN 100005 //#define ivorysi using namespace std; typedef long long int64; typedef double db; template<class T> void read(T &res) { res = 0;char c = getchar();T f = 1; while(c < '0' || c > '9') { if(c == '-') f = -1; c = getchar(); } while(c >= '0' && c <= '9') { res = res * 10 + c - '0'; c = getchar(); } res *= f; } template<class T> void out(T x) { if(x < 0) {x = -x;putchar('-');} if(x >= 10) { out(x / 10); } putchar('0' + x % 10); } int N,M; struct node { int to,next; }E[MAXN * 2]; int sumE,head[MAXN],c[MAXN]; int dfn[MAXN],son[MAXN],siz[MAXN],top[MAXN],dep[MAXN],fa[MAXN],idx,seq[MAXN]; int g[MAXN][2]; void add(int u,int v) { E[++sumE].to = v; E[sumE].next = head[u]; head[u] = sumE; } void dfs1(int u) { dep[u] = dep[fa[u]] + 1; siz[u] = 1; for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(v != fa[u]) { fa[v] = u; dfs1(v); siz[u] += siz[v]; if(siz[v] > siz[son[u]]) son[u] = v; } } for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(v != fa[u] && v != son[u]) { g[u][1] += siz[v]; } } } void dfs2(int u) { dfn[u] = ++idx;seq[idx] = u; if(!top[u]) top[u] = u; if(son[u]) {top[son[u]] = top[u];dfs2(son[u]);} for(int i = head[u] ; i ; i = E[i].next) { int v = E[i].to; if(v != fa[u] && v != son[u]) dfs2(v); } } namespace seg_tr { struct node { int L,R; int val,lz; bool sc,col; }tr[MAXN * 4]; #define lc(u) u << 1 #define rc(u) u << 1 | 1 #define val(u) tr[u].val #define lz(u) tr[u].lz #define sc(u) tr[u].sc #define col(u) tr[u].col void addlz(int u,int v) { val(u) += v;lz(u) += v; } void push_down(int u) { if(tr[u].lz) { addlz(lc(u),tr[u].lz); addlz(rc(u),tr[u].lz); } tr[u].lz = 0; } void update(int u) { if(sc(lc(u)) && sc(rc(u)) && !(col(lc(u)) ^ col(rc(u)) ) ) { sc(u) = 1;col(u) = col(lc(u)); } else sc(u) = 0; } void build(int u,int l,int r) { tr[u].L = l;tr[u].R = r; if(l == r) { tr[u].sc = 1;tr[u].col = c[seq[l]]; tr[u].val = siz[seq[l]];tr[u].lz = 0; return; } int mid = (l + r) >> 1; build(u << 1,l,mid); build(u << 1 | 1,mid + 1,r); update(u); } int query(int u,int p) { if(tr[u].L == tr[u].R) return tr[u].val; push_down(u); int mid = (tr[u].L + tr[u].R) >> 1; if(p <= mid) return query(lc(u),p); else if(p > mid) return query(rc(u),p); } void add(int u,int l,int r,int v) { if(tr[u].L == l && tr[u].R == r) {addlz(u,v);return;} push_down(u); int mid = (tr[u].L + tr[u].R) >> 1; if(r <= mid) add(lc(u),l,r,v); else if(l > mid) add(rc(u),l,r,v); else { add(lc(u),l,mid,v); add(rc(u),mid + 1,r,v); } } void change(int u,int p,int v,bool on) { if(tr[u].L == tr[u].R) { tr[u].val = v; tr[u].col = on; return; } push_down(u); int mid = (tr[u].L + tr[u].R) >> 1; if(p <= mid) change(lc(u),p,v,on); else change(rc(u),p,v,on); update(u); } int query_sc(int u,int l,int r) { if(tr[u].L == l && tr[u].R == r) return tr[u].sc; push_down(u); int mid = (tr[u].L + tr[u].R) >> 1; if(r <= mid) return query_sc(lc(u),l,r); else if(l > mid) return query_sc(rc(u),l,r); else { return query_sc(lc(u),l,mid) && query_sc(rc(u),mid + 1,r) && c[seq[mid]] == c[seq[mid + 1]]; } } int Query(int p) { return query(1,dfn[p]); } void Add(int l,int r,int v) { add(1,l,r,v); } void Change(int p,int v,bool on) { change(1,dfn[p],v,on); } bool Query_sc(int l,int r) { return query_sc(1,l,r); } } int Find_same_color(int u) { while(1) { if(seg_tr::Query_sc(dfn[top[u]],dfn[u])) { if(top[u] == 1) return 1; if(c[fa[top[u]]] != c[u]) return top[u]; u = fa[top[u]]; } else { int L = dfn[top[u]] + 1,R = dfn[u]; while(L < R) { int mid = (L + R) >> 1; if(seg_tr::Query_sc(mid,dfn[u])) R = mid; else L = mid + 1; } return seq[L]; } } } void Change_Path(int u,int v,int d) { while(top[u] != top[v]) { seg_tr::Add(dfn[top[u]],dfn[u],d); g[fa[top[u]]][c[top[u]]] += d; u = fa[top[u]]; } seg_tr::Add(dfn[v],dfn[u],d); if(v == top[u]) g[fa[v]][c[v]] += d; } void Init() { read(N); int u,v; for(int i = 1 ; i <= N ; ++i) c[i] = 1; for(int i = 1 ; i < N ; ++i) { read(u);read(v); add(u,v);add(v,u); } dfs1(1);dfs2(1); seg_tr::build(1,1,N); } void Solve() { read(M); int op,u; for(int i = 1 ; i <= M ; ++i) { read(op);read(u); if(!op) { out(seg_tr::Query(Find_same_color(u)));enter; } else { int nv = 1 + g[u][c[u] ^ 1] + (son[u] && c[son[u]] == (c[u] ^ 1) ? seg_tr::Query(son[u]) : 0); int ov = seg_tr::Query(u); if(u == 1) { seg_tr::Change(u,nv,c[u] ^ 1);c[u] ^= 1; } else { if(u == top[u]) { g[fa[u]][c[u]] -= ov; g[fa[u]][c[u] ^ 1] += nv; } int t = Find_same_color(fa[u]); if(c[fa[u]] == c[u]) Change_Path(fa[u],t,-ov); else Change_Path(fa[u],t,nv); seg_tr::Change(u,nv,c[u] ^ 1);c[u] ^= 1; } } } } int main() { #ifdef ivorysi freopen("f1.in","r",stdin); #endif Init(); Solve(); return 0; }