1A!!! 哈哈哈哈哈没看题解 没套模板哈哈哈哈 太感动了!!

如果只是线段树的话这道题倒是不难,只要记录左右边界就好了,类似很久以前做的hotel的题

但是树上相邻的段会有连续的

树上top[x]和fa[top[x]]是连续的,但是线段树上是算不到的,所以要判断下

线段树记录的是区间的数量,但是求单点的时候求得是颜色,需要注意下

#include <iostream>
#include <cstring>
#include <cstdio> using namespace std;
const int N = ;
int a[N]; struct Edge {
int to, next;
} edge[N*];
int head[N], cntE; void addedge(int u, int v) {
edge[cntE].to = v; edge[cntE].next = head[u]; head[u] = cntE++;
edge[cntE].to = u; edge[cntE].next = head[v]; head[v] = cntE++;
} int dep[N], fa[N], sz[N], son[N];
void dfs1(int u, int pre, int d) {
dep[u] = d;
sz[u] = ;
fa[u] = pre;
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (v != pre) {
dfs1(v, u, d+);
sz[u] += sz[v];
if (son[u] == - || sz[v] > sz[son[u]]) son[u] = v;
}
}
} int top[N], dfn[N], rk[N], idx;
void dfs2(int u, int tp) {
top[u] = tp;
dfn[u] = ++idx;
rk[idx] = u;
if (son[u] == -) return ;
dfs2(son[u], tp);
for (int i = head[u]; ~i; i = edge[i].next) {
int v = edge[i].to;
if (v != fa[u] && v != son[u]) {
dfs2(v, v);
}
}
} int tr[N<<], ltr[N<<], rtr[N<<]; // tr[i] means the number of color segment
int fg[N<<];
#define lson o<<1
#define rson o<<1|1 void pushup(int o) {
ltr[o] = ltr[lson];
rtr[o] = rtr[rson];
tr[o] = tr[lson] + tr[rson];
if (rtr[lson] == ltr[rson]) tr[o]--;
} void pushdown(int o) {
if (fg[o]) {
tr[lson] = tr[rson] = ;
fg[lson] = fg[rson] = fg[o];
ltr[lson] = ltr[rson] = ltr[o];
rtr[lson] = rtr[rson] = rtr[o];
fg[o] = ;
}
} void build(int o, int l, int r) {
fg[o] = ;
if (l == r) {
tr[o] = ;
ltr[o] = rtr[o] = a[rk[l]];
return;
}
int mid = (l+r) >> ;
build(lson, l, mid);
build(rson, mid+, r);
pushup(o);
} void change(int o, int l, int r, int L, int R, int v) {
if (l >= L && r <= R) {
fg[o] = ;
tr[o] = ;
ltr[o] = rtr[o] = v;
return ;
}
pushdown(o);
int mid = (l+r) >> ;
if (mid >= L) change(lson, l, mid, L, R, v);
if (mid < R) change(rson, mid+, r, L, R, v);
pushup(o);
} void CHANGE(int x, int y, int n, int c) {
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
change(, , n, dfn[top[x]], dfn[x], c);
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
change(, , n, dfn[x], dfn[y], c);
} int query(int o, int l, int r, int L, int R) {
if (l >= L && r <= R) return tr[o];
pushdown(o);
int mid = (l+r) >> ;
if (mid < L) {
return query(rson, mid+, r, L, R);
} else if (mid >= R) {
return query(lson, l, mid, L, R);
} else {
int ans = query(lson, l, mid, L, R);
ans += query(rson, mid+, r, L, R);
if (ltr[rson] == rtr[lson]) ans--;
return ans;
}
} int qq(int o, int l, int r, int p) {
if (l == r) return ltr[o];
pushdown(o);
int mid = (l+r) >> ;
if (mid >= p) return qq(lson, l, mid, p);
return qq(rson, mid+, r, p);
} int QUERY(int x, int y, int n) {
int ans = ;
while (top[x] != top[y]) {
if (dep[top[x]] < dep[top[y]]) swap(x, y);
ans += query(, , n, dfn[top[x]], dfn[x]);
if (qq(, , n, dfn[top[x]]) == qq(, , n, dfn[fa[top[x]]])) --ans;
x = fa[top[x]];
}
if (dep[x] > dep[y]) swap(x, y);
ans += query(, , n, dfn[x], dfn[y]);
return ans;
} void init() {
memset(head, -, sizeof head);
memset(son, -, sizeof son);
idx = cntE = ;
} int main()
{
//freopen("in.txt", "r", stdin);
int n, m;
while (~scanf("%d%d", &n, &m)) {
init();
for (int i = ; i <= n; ++i) scanf("%d", &a[i]);
int u, v, c;
for (int i = ; i < n; ++i) {
scanf("%d%d", &u, &v);
addedge(u, v);
}
dfs1(, , ); dfs2(, ); build(, , n); char op[];
while (m--) {
scanf("%s", op);
if (*op == 'Q') {
scanf("%d%d", &u, &v);
printf("%d\n", QUERY(u, v, n));
} else {
scanf("%d%d%d", &u, &v, &c);
CHANGE(u, v, n, c);
}
}
}
return ;
}

HYSBZ 2243-染色 (树链剖分)的更多相关文章

  1. hysbz 2243 染色(树链剖分)

    题目链接:hysbz 2243 染色 题目大意:略. 解题思路:树链剖分+线段树的区间合并,可是区间合并比較简单,节点仅仅要记录左右端点的颜色就可以. #include <cstdio> ...

  2. HYSBZ - 2243 染色 (树链剖分+线段树)

    题意:树上每个结点有自己的颜色,支持两种操作:1.将u到v路径上的点颜色修改为c; 2.求u到v路径上有多少段不同的颜色. 分析:树剖之后用线段树维护区间颜色段数.区间查询区间修改.线段树结点中维护的 ...

  3. BZOJ 2243 染色 | 树链剖分模板题进阶版

    BZOJ 2243 染色 | 树链剖分模板题进阶版 这道题呢~就是个带区间修改的树链剖分~ 如何区间修改?跟树链剖分的区间询问一个道理,再加上线段树的区间修改就好了. 这道题要注意的是,无论是线段树上 ...

  4. HYSBZ 2243(树链剖分)

    题目连接:http://acm.hust.edu.cn/vjudge/contest/view.action?cid=28982#problem/D 题意:给定一棵有n个节点的无根树及点权和m个操作, ...

  5. BZOJ 2243 染色 树链剖分

    题意: 给出一棵树,每个顶点上有个颜色\(c_i\). 有两种操作: C a b c 将\(a \to b\)的路径所有顶点上的颜色变为c Q a b 查询\(a \to b\)的路径上的颜色段数,连 ...

  6. BZOJ - 2243 染色 (树链剖分+线段树+区间合并)

    题目链接 线段树维护区间连续段个数即可.设lc为区间左端点颜色,rc为区间右端点颜色,则合并两区间的时候,如果左区间右端点和右区间左端点颜色相同,则连续段个数-1. 在树链上的区间合并可以定义一个结构 ...

  7. BZOJ 2243: [SDOI2011]染色 [树链剖分]

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

  8. bzoj-2243 2243: [SDOI2011]染色(树链剖分)

    题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 6267  Solved: 2291 Descript ...

  9. Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树

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

  10. BZOJ 2243: [SDOI2011]染色 树链剖分 倍增lca 线段树

    2243: [SDOI2011]染色 Time Limit: 20 Sec  Memory Limit: 256 MB 题目连接 http://www.lydsy.com/JudgeOnline/pr ...

随机推荐

  1. Java API —— System类

    1.System类概述         System 类包含一些有用的类字段和方法.它不能被实例化.  2.成员方法         public static void gc():运行垃圾回收器   ...

  2. tomcat作为windows服务启动失败解决方法

    再使用如下方法注册windows服务时,出现问题: set CATALINA_BASE=E:\tomcat\tomcat-web-server set CATALINA_HOME=E:\tomcat\ ...

  3. BAT面经

    http://bbs.csdn.net/topics/390734210?page=4 注意评论以及文章原地址

  4. org.json.JSONObject与com.google.gson.Gson

    org.json库为JSON创始人编写的解析JSON的java库,Gson为Google为我们提供的解析JSON格式数据的库. Gson里最重要的对象有2个Gson 和GsonBuilder. Gso ...

  5. Windows下tuxedo配置

    setenv.cmd rem (c) 2003 BEA Systems, Inc. All Rights Reserved. rem Copyright (c) 2000 BEA Systems, I ...

  6. linq 之左连接

    List<ArticleModel> articleList = articleRepository.GetAllArticle(); List<UsersModel> use ...

  7. liunx下mysql数据库使用之三范式,关系模型设计注意项,安装目录结构

    数据库的三范式第一范式===>每行记录的属性,是原子的,拆到不可拆为止.===>例如:一个人的籍贯,可以拆分为,省,市,县,乡,村 第二范式===>每行记录的非主属性(非主键属性), ...

  8. 【转 iOS 8 Auto Layout界面自动布局系列2-使用Xcode的Interface Builder添加布局约束

    原文网址:http://blog.csdn.net/pucker/article/details/41843511 上一篇文章<iOS 8界面自动布局系列-1>简要介绍了iOS界面布局方式 ...

  9. VS2013密匙

    在网上找到的,亲测有用: BWG7X-J98B3-W34RT-33B3R-JVYW9

  10. 用命令行(CMD)中启动和关闭ORACLE服务

    lsnrctl start开启监听 lsnrctl stop停止监听 net start oracleserviceoracle开启oracle服务 net stop oracleserviceora ...