BZOJ2243——[SDOI2011]染色
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]染色的更多相关文章
- BZOJ2243 SDOI2011 染色 【树链剖分】
BZOJ2243 SDOI2011 染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色 ...
- bzoj2243[SDOI2011]染色 树链剖分+线段树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 9012 Solved: 3375[Submit][Status ...
- [bzoj2243][SDOI2011]染色
Description 给定一棵有$n$个节点的无根树和$m$个操作,操作有$2$类: 1.将节点$a$到节点$b$路径上所有点都染成颜色$c$; 2.询问节点$a$到节点$b$路径上的颜色段数量(连 ...
- BZOJ2243[SDOI2011]染色——树链剖分+线段树
题目描述 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如“112221 ...
- [BZOJ2243][SDOI2011]染色 解题报告|树链剖分
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段),如“ ...
- BZOJ2243 [SDOI2011]染色(树链剖分+线段树合并)
题目链接 BZOJ2243 树链剖分 $+$ 线段树 线段树每个节点维护$lc$, $rc$, $s$ $lc$代表该区间的最左端的颜色,$rc$代表该区间的最右端的颜色 $s$代表该区间的所有连续颜 ...
- BZOJ2243: [SDOI2011]染色(树链剖分/LCT)
Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的颜色段数量(连续相同颜色被认为是同一段), 如 ...
- bzoj2243: [SDOI2011]染色--线段树+树链剖分
此题代码量较大..但是打起来很爽 原本不用lca做一直wa不知道为什么.. 后来改lca重打了一遍= =结果一遍就AC了orz 题目比较裸,也挺容易打,主要是因为思路可以比较清晰 另:加读入优化比没加 ...
- bzoj2243 sdoi2011 染色 paint
明明是裸树剖 竟然调了这么久好蛋疼 大概是自己比较水的原因吧 顺便+fastio来gangbang #include<iostream> #include<cstring> # ...
随机推荐
- DockerProblem
if you try to run the daemon manually: sudo /usr/bin/docker daemon And the error is: "FATA[0000 ...
- Struts2(一)入门及工作原理
Apache Struts 2 是一种流行的 Java模型 - 视图 - 控制器(MVC)框架,成功地结合了 WebWork和Struts1.x 两种 web 框架. Apache Struts2与S ...
- IOS中在自定义控件(非视图控制器)的视图跳转中 代理方法与代码块的比较
//代码块与代替代理的设计方法 我就以在自定义视图中(非视图控制器,不能实现视图控制功能),通过代理和代码块两种方法分别实现视图的跳转,进行对比 首先自定义了一个视图,上面有一个已经注册了得BUtto ...
- 【转】jquery的extend和fn.extend
jQuery为开发插件提拱了两个方法,分别是: jQuery.fn.extend(object); jQuery.extend(object); jQuery.extend(object); 为扩展j ...
- 9.19 JS数组
数组:相同类型数据的集合强类型语言:1数组里面只能存放相同数据类型的数据 2定义数组的时候需要制定一个长度(可以存放的元素数量) 3内存空间连续集合:1.可以存放任意类型的数据 ...
- python学习笔记-(三)条件判断和循环
1.条件判断语句 Python中条件选择语句的关键字为:if .elif .else这三个.其基本形式如下: age_of_cc = 27 age = int(input("guessage ...
- phpexcel操作
<?php include './PHPExcel/PHPExcel.php'; include './PHPExcel/PHPExcel/Writer/Excel2007.php'; //或者 ...
- CodeForces 698A Vacations
题目链接 : http://codeforces.com/problemset/problem/698/A 题目大意: 阿Q有n天假期,假期中有三种安排 休息.健身.比赛.每天有三种选择条件: 0 健 ...
- git add
一.前言git add命令主要用于把我们要提交的文件的信息添加到索引库中.当我们使用git commit时,git将依据索引库中的内容来进行文件的提交. 二.基本git add <path> ...
- 用淘宝ip地址库查ip
这是一个通过调用淘宝ip地址库实现ip地址查询的功能类 using System; using System.Collections.Generic; using System.Linq; using ...