码迷,mamicode.com
首页 > 其他好文 > 详细

P2486 [SDOI2011]染色

时间:2018-05-04 21:59:17      阅读:205      评论:0      收藏:0      [点我收藏+]

标签:sam   mod   i++   wap   badge   bit   +=   树查询   ble   

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]染色

标签:sam   mod   i++   wap   badge   bit   +=   树查询   ble   

原文地址:https://www.cnblogs.com/EdSheeran/p/8992606.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!