P2486 [SDOI2011]染色
阿新 • • 發佈:2018-05-04
+= www ace 鏈接 close || 情況 orange pac
P2486 [SDOI2011]染色
鏈接:https://www.luogu.org/problemnew/show/P2486
題目描述
輸入輸出格式
輸入格式:
輸出格式:
對於每個詢問操作,輸出一行答案。
輸入輸出樣例
輸入樣例#1: 復制6 5 2 2 1 2 1 1 1 2 1 3 2 4 2 5 2 6 Q 3 5 C 2 1 1 Q 3 5 C 5 1 2 Q 3 5輸出樣例#1: 復制
3 1 2
說明
題解:樹連剖分+細節,用二進制記錄某段染色情況,並記錄最邊上的顏色,不能維護一段中連續顏色數(顯然);
線段樹查詢的時候要註意合並兩端細節,樹剖時也要記錄上次最邊上的顏色,註意是父親的;
#include <bits/stdc++.h> using namespace std; const int maxn = 100005; int n,m; struct edge{ int v,nxt; }G[maxn << 1]; int h[maxn], tot, dfn[maxn], siz[maxn], fa[maxn], top[maxn], son[maxn], in[maxn], dep[maxn], idx; int a[maxn],LLC,RRC; void add(int u, int v){ G[++tot].nxt = h[u]; G[tot].vView Code= v; h[u] = tot; } void dfs1(int u, int f){ fa[u] = f; siz[u] = 1; dep[u] = dep[f] + 1; for(int i = h[u]; i; i = G[i].nxt){ int v = G[i].v; if(v == f)continue; dfs1(v, u); siz[u] += siz[v]; if(siz[son[u]] < siz[v]) son[u] = v; } } voiddfs2(int u, int f){ in[u] = ++idx; top[u] = f; dfn[idx] = a[u]; if(son[u])dfs2(son[u], f); for(int i = h[u]; i; i = G[i].nxt){ int v = G[i].v; if(v == fa[u] || v == son[u])continue; dfs2(v, v); } } struct Node{ int sum, lc, rc, delta; Node *ls, *rs; void down(int l, int r){ if(delta == -1)return; ls -> delta = rs -> delta = delta; ls -> lc = rs -> lc = ls -> rc = rs -> rc = delta; ls -> sum = rs -> sum = 1; delta = -1; } void up(){ sum = ls -> sum + rs -> sum; lc = ls -> lc; rc = rs -> rc; if(ls -> rc == rs -> lc)sum--; } }pool[maxn << 2], *root, *tail = pool; #define Ls l, m, nd->ls #define Rs m+1, r, nd->rs Node * build(int l = 1, int r = n){ Node * nd = ++ tail; if(l == r){ nd -> lc = nd -> rc = dfn[l]; nd -> delta = -1;nd->sum = 1; } else { int m = (l + r) >> 1; nd -> ls = build(l, m); nd -> rs = build(m+1, r); nd -> up(); nd -> delta = -1; } //printf("%d %d %d %d kkk\n",l,r,nd->lc,nd->rc); return nd; } void modify(int delta, int L, int R, int l = 1, int r = n, Node * nd = root){ if(L <= l && R >= r){ nd -> delta = nd -> lc = nd -> rc = delta; nd -> sum = 1; } else { nd -> down(l, r); int m = (l + r) >> 1; if(L <= m)modify(delta, L, R, Ls); if(R > m)modify(delta, L, R, Rs); nd -> up(); } } int query(int L, int R, int l = 1, int r = n, Node * nd = root){ //printf("%d %d %d %d\n",l,r,nd->lc,nd->rc); if(l == L)LLC = nd->lc; if(r == R)RRC = nd->rc; if(L <= l && R >= r)return nd -> sum; nd -> down(l, r); int ans = 0; int m = (l + r) >> 1; if(L <= m)ans += query(L, R, Ls); if(R > m)ans += query(L, R, Rs); if(L <= m && R > m && nd -> ls -> rc == nd -> rs -> lc)ans--; return ans; } int lca_query(int u, int v){ int ans = 0, ans1 = -1, ans2 = -1; while(top[u] != top[v]){ if(dep[top[u]] < dep[top[v]]) swap(u, v), swap(ans1, ans2); ans += query(in[top[u]], in[u]); u = fa[top[u]]; if(ans1 == RRC)ans--; ans1 = LLC; } if(dep[u] < dep[v]) swap(u, v), swap(ans1, ans2); ans += query(in[v], in[u]); if(ans1 == RRC)ans--; if(ans2 == LLC)ans--; return ans; } void lca_modify(int u, int v, int del){ while(top[u] != top[v]){ if(dep[top[u]] < dep[top[v]]) swap(u, v); modify(del, in[top[u]], in[u]); u = fa[top[u]]; } if(dep[u] < dep[v])swap(u, v); modify(del, in[v], in[u]); } int main() { scanf("%d%d",&n,&m); for(int i = 1; i <= n; i++)scanf("%d",&a[i]); for(int i = 1; i < n; i++){ int u,v; scanf("%d%d",&u,&v); add(u, v);add(v,u); } dfs1(1, 0); dfs2(1, 0); root = build(); while(m--){ char Q; int l, r, del; cin>>Q; if(Q == ‘C‘){ scanf("%d%d%d",&l,&r,&del); lca_modify(l, r, del); } else { scanf("%d%d",&l,&r); printf("%d\n",lca_query(l, r)); } } return 0; }
P2486 [SDOI2011]染色