Description

题库链接

给定一棵有 \(n\) 个节点的无根树和 \(m\) 个操作,操作有 \(2\) 类:

  1. 将节点 \(a\) 到节点 \(b\) 路径上所有点都染成颜色 \(c\) ;
  2. 询问节点 \(a\) 到节点 \(b\) 路径上的颜色段数量(连续相同颜色被认为是同一段)

Solution

线段树苟题。因为没有下传 \(lazy\) 标记调了一上午。

Code

//It is made by Awson on 2018.3.4
#include <bits/stdc++.h>
#define LL long long
#define dob complex<double>
#define Abs(a) ((a) < 0 ? (-(a)) : (a))
#define Max(a, b) ((a) > (b) ? (a) : (b))
#define Min(a, b) ((a) < (b) ? (a) : (b))
#define Swap(a, b) ((a) ^= (b), (b) ^= (a), (a) ^= (b))
#define writeln(x) (write(x), putchar('\n'))
#define lowbit(x) ((x)&(-(x)))
using namespace std;
const int N = 1e5;
void read(int &x) {
char ch; bool flag = 0;
for (ch = getchar(); !isdigit(ch) && ((flag |= (ch == '-')) || 1); ch = getchar());
for (x = 0; isdigit(ch); x = (x<<1)+(x<<3)+ch-48, ch = getchar());
x *= 1-2*flag;
}
void print(int x) {if (x > 9) print(x/10); putchar(x%10+48); }
void write(int x) {if (x < 0) putchar('-'); print(Abs(x)); } int n, m, c[N+5], a[N+5], u, v, ca;
struct tt {int to, next; }edge[(N<<1)+5];
int path[N+5], Top;
int size[N+5], id[N+5], son[N+5], top[N+5], dep[N+5], fa[N+5], pos;
char ch[5];
struct node {
int l, r, cnt;
node() {}
node(int _l, int _r, int _cnt) {l = _l, r = _r, cnt = _cnt; }
node operator + (const node &b) const {node tmp; tmp.l = l, tmp.r = b.r, tmp.cnt = cnt+b.cnt-(r==b.l); return tmp; }
};
struct Segment_tree {
#define lr(o) (o<<1)
#define rr(o) (o<<1|1)
node sgm[(N<<2)+5]; int lazy[(N<<2)+5];
void pushdown(int o) {sgm[lr(o)] = sgm[rr(o)] = sgm[o]; lazy[lr(o)] = lazy[rr(o)] = 1; lazy[o] = 0; }
void build(int o, int l, int r) {
if (l == r) {sgm[o] = node(a[l], a[l], 1); return; }
int mid = (l+r)>>1;
build(lr(o), l, mid); build(rr(o), mid+1, r); sgm[o] = sgm[lr(o)]+sgm[rr(o)];
}
node query(int o, int l, int r, int a, int b) {
if (a <= l && r <= b) return sgm[o];
if (lazy[o]) pushdown(o); int mid = (l+r)>>1;
if (b <= mid) return query(lr(o), l, mid, a, b);
if (a > mid) return query(rr(o), mid+1, r, a, b);
return query(lr(o), l, mid, a, b)+query(rr(o), mid+1, r, a, b);
}
void update(int o, int l, int r, int a, int b, int col) {
if (a <= l && r <= b) {sgm[o] = node(col, col, 1), lazy[o] = 1; return; }
if (lazy[o]) pushdown(o); int mid = (l+r)>>1;
if (a <= mid) update(lr(o), l, mid, a, b, col);
if (b > mid) update(rr(o), mid+1, r, a, b, col);
sgm[o] = sgm[lr(o)]+sgm[rr(o)];
}
}T; void add(int u, int v) {edge[++Top].to = v, edge[Top].next = path[u], path[u] = Top; }
void dfs1(int o, int depth, int father) {
dep[o] = depth, size[o] = 1, fa[o] = father;
for (int i = path[o]; i; i = edge[i].next)
if (dep[edge[i].to] == 0) {
dfs1(edge[i].to, depth+1, o); size[o] += size[edge[i].to];
if (size[edge[i].to] > size[son[o]]) son[o] = edge[i].to;
}
}
void dfs2(int o, int tp) {
id[o] = ++pos, a[pos] = c[o], top[o] = tp;
if (son[o]) dfs2(son[o], tp);
for (int i = path[o]; i; i = edge[i].next)
if (edge[i].to != fa[o] && edge[i].to != son[o]) dfs2(edge[i].to, edge[i].to);
}
void update(int u, int v, int c) {
while (top[u] != top[v]) {
if (dep[top[u]] < dep[top[v]]) Swap(u, v);
T.update(1, 1, n, id[top[u]], id[u], c);
u = fa[top[u]];
}
if (dep[u] < dep[v]) Swap(u, v);
T.update(1, 1, n, id[v], id[u], c);
}
int query(int u, int v) {
node n1, n2; int f1 = 1, f2 = 1;
while (top[u] != top[v]) {
if (dep[top[u]] > dep[top[v]]) {
if (f1) n1 = T.query(1, 1, n, id[top[u]], id[u]);
else n1 = T.query(1, 1, n, id[top[u]], id[u])+n1;
u = fa[top[u]]; f1 = 0;
}else {
if (f2) n2 = T.query(1, 1, n, id[top[v]], id[v]);
else n2 = T.query(1, 1, n, id[top[v]], id[v])+n2;
v = fa[top[v]]; f2 = 0;
}
}
if (dep[u] > dep[v]) {
if (f1) n1 = T.query(1, 1, n, id[v], id[u]);
else n1 = T.query(1, 1, n, id[v], id[u])+n1; f1 = 0;
}else {
if (f2) n2 = T.query(1, 1, n, id[u], id[v]);
else n2 = T.query(1, 1, n, id[u], id[v])+n2; f2 = 0;
}
if (f1) return n2.cnt;
if (f2) return n1.cnt;
Swap(n1.l, n1.r); n1 = n1+n2; return n1.cnt;
}
void work() {
read(n), read(m); for (int i = 1; i <= n; i++) read(c[i]);
for (int i = 1; i < n; i++) read(u), read(v), add(u, v), add(v, u);
dfs1(1, 1, 0), dfs2(1, 1); T.build(1, 1, n);
while (m--) {
scanf("%s", ch);
if (ch[0] == 'Q') read(u), read(v), writeln(query(u, v));
else read(u), read(v), read(ca), update(u, v, ca);
}
}
int main() {
work(); return 0;
}

[SDOI 2011]染色的更多相关文章

  1. [BZOJ 2243] [SDOI 2011] 染色 【树链剖分】

    题目链接:BZOJ - 2243 题目分析 树链剖分...写了200+行...Debug了整整一天+... 静态读代码读了 5 遍 ,没发现错误,自己做小数据也过了. 提交之后全 WA . ————— ...

  2. BZOJ 2243 SDOI 2011染色

    题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=2243 算法讨论: 树链剖分把树放到线段树上.然后线段树的每个节点要维护的东西有左端点的颜色 ...

  3. 解题: SDOI 2011 染色

    题面 强行把序列问题通过树剖套在树上...算了算是回顾了一下树剖的思想=.= 每次树上跳的时候注意跳的同时维护当前拼出来的左右两条链的靠上的端点,然后拼起来的时候讨论一下拼接点,最后一下左右两边的端点 ...

  4. 【SDOI 2011】染色

    [题目链接] 点击打开链接 [算法] 树链剖分 [代码] 本题,笔者求最近公共祖先并没有用树链剖分“往上跳”的方式,而是用倍增法.笔者认为这样比较好写,代码可读性 比较高 此外,笔者的线段树并没有用懒 ...

  5. 【codevs 1565】【SDOI 2011】计算器 快速幂+拓展欧几里得+BSGS算法

    BSGS算法是meet in the middle思想的一种应用,参考Yveh的博客我学会了BSGS的模版和hash表模板,,, 现在才会hash是不是太弱了,,, #include<cmath ...

  6. [bzoj2286][Sdoi 2011]消耗战

    [bzoj2286]消耗战 标签: 虚树 DP 题目链接 题解 很容易找出\(O(mn)\)的做法. 只需要每次都dp一遍. 但是m和n是同阶的,所以这样肯定会T的. 注意到dp的时候有很多节点是不需 ...

  7. [SDOI 2011]黑白棋

    Description 题库链接 给出一个 \(1\times n\) 的棋盘,棋盘上有 \(k\) 个棋子,一半是黑色,一半是白色.最左边是白色棋子,最右边是黑色棋子,相邻的棋子颜色不同. 小 \( ...

  8. [SDOI 2011]消耗战

    Description 题库链接 给你一棵 \(n\) 个节点根节点为 \(1\) 的有根树,有边权. \(m\) 次询问,每次给出 \(k_i\) 个关键点.询问切断一些边,使这些点到根节点不连通, ...

  9. [SDOI 2011]计算器

    Description 你被要求设计一个计算器完成以下三项任务: 1.给定y,z,p,计算Y^Z Mod P 的值: 2.给定y,z,p,计算满足xy≡ Z ( mod P )的最小非负整数: 3.给 ...

随机推荐

  1. JavaWeb学习笔记二 Http协议和Tomcat服务器

    Http协议 HTTP,超文本传输协议(HyperText Transfer Protocol),是互联网上应用最为广泛的一种网络协议.所有的WWW文件都必须遵守这个标准.设计HTTP最初的目的是为 ...

  2. 云计算--网络原理与应用--20171120--VLAN与三层交换机配置

    什么是VLAN及其配置 Trunk的原理与配置 三层交换机的基本配置 实验:配置一个三层交换机 一 VLAN 的概念及优势 VLAN(virtual local area network)就是虚拟局域 ...

  3. [开源] yvm - 自制Java虚拟机

    项目地址 : https://github.com/racaljk/yvm 虚拟机现在已可运行(不过还有很多待发现待修复的bugs),已支持语言特性有: Java基本算术运算,流程控制语句,面向对象. ...

  4. C语言--总结报告

    1.当初你是如何做出选择计算机专业的决定的? 经过一个学期,你的看法改变了么,为什么? 你觉得计算机是你喜欢的领域吗,它是你擅长的领域吗? 为什么? 当初填报志愿我是有很明确的专业方向的,就是IT类的 ...

  5. 201621123050 《Java程序设计》第9周学习总结

    1. 本周学习总结 1.1 以你喜欢的方式(思维导图或其他)归纳总结集合与泛型相关内容. 1.2 选做:收集你认为有用的代码片段 ①foreach循环 for (String e : map.keyS ...

  6. 201621123040 《Java程序设计》第1周学习总结

    1.本周学习总结 关键词 JAVA概述 HelloWorld JDK JRE JVM JAVA基础语法 相关联系 通过一周的学习,我对JAVA有了初步的了解,JAVA是一种优秀的跨平台编写代码的应用平 ...

  7. iOS开发-添加圆角效果高效实现

    圆角(RounderCorner)是一种很常见的视图效果,相比于直角,它更加柔和优美,易于接受.但很多人并不清楚如何设置圆角的正确方式和原理.设置圆角会带来一定的性能损耗,如何提高性能是另一个需要重点 ...

  8. 【iOS】OC-时间转化的时区问题

    -(void)testTime{ NSDate *now = [NSDate date];//根据当前系统的时区产生当前的时间,绝对时间,所以同为中午12点,不同的时区,这个时间是不同的. NSDat ...

  9. 剑指offer-数组中出现次数超过一半的数字

    题目描述 数组中有一个数字出现的次数超过数组长度的一半,请找出这个数字.例如输入一个长度为9的数组{1,2,3,2,2,2,5,4,2}.由于数字2在数组中出现了5次,超过数组长度的一半,因此输出2. ...

  10. python中的赋值与深浅拷贝

    Python当中对于拷贝,分为两种类型.一种是数字和字符串,另一种就是列表.元组.字典等其他类型了. 一.数字和字符串的拷贝 1.赋值 举个栗子: a1 = 123123 a2 = 123123 # ...