P2486 [SDOI2011]染色
Posted Ed_Sheeran
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了P2486 [SDOI2011]染色相关的知识,希望对你有一定的参考价值。
P2486 [SDOI2011]染色
链接:https://www.luogu.org/problemnew/show/P2486
题目描述
输入输出格式
输入格式:
输出格式:
对于每个询问操作,输出一行答案。
输入输出样例
说明
题解:树连剖分+细节,用二进制记录某段染色情况,并记录最边上的颜色,不能维护一段中连续颜色数(显然);
线段树查询的时候要注意合并两端细节,树剖时也要记录上次最边上的颜色,注意是父亲的;
#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].v = 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; } } void dfs2(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]染色的主要内容,如果未能解决你的问题,请参考以下文章