1. 程式人生 > >P2486 [SDOI2011]染色

P2486 [SDOI2011]染色

+= 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].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; }
View Code

P2486 [SDOI2011]染色