1、题目大意:给个树,然后树上每个点都有颜色,然后会有路径的修改,有个询问,询问一条路径上的颜色分成了几段

2、分析:首先这个修改是树剖可以做的,对吧,但是这个分成了几段怎么搞呢,我们的树剖的不是要建线段树吗

我们的线段树存这样的几个值,一个是这个区间被分成了几段,另外就是这个区间的最左边的颜色和最右边的颜色

这样,我们在区间合并的时候把两个区间的段数加起来

然后用左区间的右端点和右区间的左端点如果相同就-1就可以了,那么这道题就做完了

#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
#define M 1000000
struct node{
    int l, ans, r;
};
struct hehe{
    int Top[M], Size[M], High[M], Fa[M], num[M], value[M];
    node q[M];
    int lazy[M];
    int tot, head[M], Next[M], son[M];
    int ST_tot;
    int n;
    inline void init(){
        ST_tot = tot = 0;
        for(int i = 1; i < M; i ++) lazy[i] = -1;
        memset(head, -1, sizeof(head));
        Top[1] = 1;
    }
    inline void pushdown(int o){
        if(lazy[o] != -1){
            lazy[2 * o] = lazy[2 * o + 1] = lazy[o];
            q[2 * o].l = q[2 * o].r = q[2 * o + 1].l = q[2 * o + 1].r = lazy[o];
            q[2 * o].ans = q[2 * o + 1].ans = 1;
            lazy[o] = -1;
        }
    }
    inline void add(int l, int r, int o, int x, int y, int k){
        if(x <= l && r <= y){
            q[o].l = q[o].r = k;
            q[o].ans = 1;
            lazy[o] = k;
            return;
        }
        int mid = (l + r) / 2;
        pushdown(o);
        if(x <= mid) add(l, mid, 2 * o, x, y, k);
        if(y > mid) add(mid + 1, r, 2 * o + 1, x, y, k);
        q[o].l = q[2 * o].l;
        q[o].r = q[2 * o + 1].r;
        q[o].ans = q[2 * o].ans + q[2 * o + 1].ans;
        if(q[2 * o].r == q[2 * o + 1].l) q[o].ans --;
    }
    inline node query(int l, int r, int o, int x, int y){
        if(x <= l && r <= y){
            return q[o];
        }
        pushdown(o);
        int mid = (l + r) / 2;
        if(x <= mid && y <= mid) return query(l, mid, 2 * o, x, y);
        else if(x > mid && y > mid) return query(mid + 1, r, 2 * o + 1, x, y);
        else{
            node ll = query(l, mid, 2 * o, x, y);
            node rr = query(mid + 1, r, 2 * o + 1, x, y);
            node ret;
            ret.l = ll.l;
            ret.r = rr.r;
            ret.ans = ll.ans + rr.ans;
            if(ll.r == rr. l) ret.ans --;
            return ret;
        }
    }
    inline void insert(int x, int y){
        tot ++;
        son[tot] = y;
        Next[tot] = head[x];
        head[x] = tot;
    }
    inline void dfs1(int x, int fa, int height){
        Fa[x] = fa;
        High[x] = height;
        for(int i = head[x]; i != -1; i = Next[i]) if(son[i] != fa){
            dfs1(son[i], x, height + 1);
            Size[x] += Size[son[i]];
        }
        Size[x] ++;
    }
    inline void dfs2(int x, int fa){
        ++ ST_tot;
        num[x] = ST_tot;
        add(1, n, 1, ST_tot, ST_tot, value[x]);
        int o = -1, sos = 0;
        for(int i = head[x]; i != -1; i = Next[i]) if(son[i] != fa){
            if(Size[son[i]] > sos){
                sos = Size[son[i]];
                o = i;
            }
        }
        if(o != -1){
            Top[son[o]] = Top[x];
            dfs2(son[o], x);
        }
        for(int i = head[x]; i != -1; i = Next[i]) if(son[i] != fa && i != o){
            Top[son[i]] = son[i];
            dfs2(son[i], x);
        }
    }
    inline void real_add(int x, int y, int k){
        while(Top[x] != Top[y]){
            if(High[Top[x]] < High[Top[y]]) swap(x, y);
            add(1, n, 1, num[Top[x]], num[x], k);
            x = Fa[Top[x]];
        }
        if(High[x] < High[y]) swap(x, y);
        add(1, n, 1, num[y], num[x], k);
        return;
    }
    inline int real_query(int x, int y){
        int tx = -1, ty = -1;
        int ret = 0;
        while(Top[x] != Top[y]){
            if(High[Top[x]] < High[Top[y]]){
                swap(x, y);
                swap(tx, ty);
            }
            node hh = query(1, n, 1, num[Top[x]], num[x]);
            ret += hh.ans;
            if(hh.r == tx) ret --;
            tx = hh.l;
            x = Fa[Top[x]];
        }
        if(High[x] < High[y]){
            swap(x, y);
            swap(tx, ty);
        }
        node hh = query(1, n, 1, num[y], num[x]);
        ret += hh.ans;
        if(hh.r == tx) ret --;
        if(hh.l == ty) ret --;
        return ret;
    }
} wt;
int main(){
    int n, m;
    scanf("%d%d", &n, &m);
    wt.n = n;
    wt.init();
    for(int i = 1; i <= n; i ++) scanf("%d", &wt.value[i]);
    for(int i = 1; i < n; i ++){
        int x, y;
        scanf("%d%d", &x, &y);
        wt.insert(x, y);
        wt.insert(y, x);
    }
    wt.dfs1(1, -1, 1);
    wt.dfs2(1, -1);
    char str[2];
    int x, y, z;
    for(int i = 1; i <= m; i ++){
        scanf("%s", str);
        if(str[0] == 'Q'){
            scanf("%d%d", &x, &y);
            printf("%d\n", wt.real_query(x, y));
        }
        else{
            scanf("%d%d%d", &x, &y, &z);
            wt.real_add(x, y, z);
        }
    }
    return 0;
}

BZOJ2243——[SDOI2011]染色的更多相关文章

  1. BZOJ2243 SDOI2011 染色 【树链剖分】

    BZOJ2243 SDOI2011 染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色 ...

  2. bzoj2243[SDOI2011]染色 树链剖分+线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 9012  Solved: 3375[Submit][Status ...

  3. [bzoj2243][SDOI2011]染色

    Description 给定一棵有$n$个节点的无根树和$m$个操作,操作有$2$类: 1.将节点$a$到节点$b$路径上所有点都染成颜色$c$; 2.询问节点$a$到节点$b$路径上的颜色段数量(连 ...

  4. BZOJ2243[SDOI2011]染色——树链剖分+线段树

    题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221 ...

  5. [BZOJ2243][SDOI2011]染色 解题报告|树链剖分

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...

  6. BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)

    题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...

  7. BZOJ2243: [SDOI2011]染色(树链剖分/LCT)

    Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如 ...

  8. bzoj2243: [SDOI2011]染色--线段树+树链剖分

    此题代码量较大..但是打起来很爽 原本不用lca做一直wa不知道为什么.. 后来改lca重打了一遍= =结果一遍就AC了orz 题目比较裸,也挺容易打,主要是因为思路可以比较清晰 另:加读入优化比没加 ...

  9. bzoj2243 sdoi2011 染色 paint

    明明是裸树剖 竟然调了这么久好蛋疼 大概是自己比较水的原因吧 顺便+fastio来gangbang #include<iostream> #include<cstring> # ...

随机推荐

  1. 我所了解的cgi

    http://www.cnblogs.com/liuzhang/p/3929198.html 当我们在谈到cgi的时候,我们在讨论什么 最早的Web服务器简单地响应浏览器发来的HTTP请求,并将存储在 ...

  2. spring boot 框架 启动更新项目,以及生成 "实体_"文件

    1.更新项目 clean  --->  更新项目 ---> package--->refresh 即可.(这几个步骤一个不能够少) 2.项目中的类的依赖关系存在,但是无法导入依赖 m ...

  3. css010 css的transform transition和animation

    css010 css的transform transition和animation 看着没有一个能想起他们是干什么的.. 1.         Transform    Transform(变形) r ...

  4. mongdb查询与排序

    db.QResult.find({'CreateDate':{'$gte' : ISODate('2016-07-01'), '$lte' : ISODate('2016-08-01')}}).sor ...

  5. Ansible facts

    facts组件是Ansible用于采集被管理机器设备信息的一个功能.可以使用setup模块查机器的所有facts信息,可以使用filter来查看指定信息.整个facts信息被包装在一个json格式的数 ...

  6. Mysql 与 Python socket

    py1.py # -*- coding: utf-8 -*- import sqlalchemy import tushare import pandas import socket import s ...

  7. Interesting things in Unity 4.5 you probably didn't know about

    http://va.lent.in/interesting-things-in-unity-4-5-you-probably-didnt-know-about/

  8. python 基本数据类型分析

    在python中,一切都是对象!对象由类创建而来,对象所拥有的功能都来自于类.在本节中,我们了解一下python基本数据类型对象具有哪些功能,我们平常是怎么使用的. 对于python,一切事物都是对象 ...

  9. linux下svn的命令

    原文地址:http://www.cnblogs.com/wanqieddy/archive/2011/06/09/2076783.html

  10. CSS学习点滴

    1.CSS :link 选择器 a:link { background-color:yellow;text-decoration:none } 参考:http://www.w3school.com.c ...