luogu2486 [SDOI2011]染色
题目大意:给定一个N个点的树,每个点有一个颜色
有M次操作,每次可以修改树某条链所有点变成一个颜色,查询某条链上点的颜色段数
树剖,线段树维护区间合并
我的代码记录的是某个区间左端点颜色、右端点颜色、除了左端点和右端点的颜色段数
需要稍微特殊处理一些情况,详见代码
#include <cstdio>
#include <vector>
using namespace std;
struct fuck
{
int l, r, cnt; //cnt=-1代表lcol=rcol 区间内只有一种颜色,-2代表区间是空的
fuck(){}
fuck(int col) : l(col), r(col), cnt(-1) {}
fuck(int l, int r, int cnt) : l(l), r(r), cnt(cnt) {}
};
fuck operator*(const fuck &l, const fuck &r)
{
if (l.cnt == -2) return r;
if (r.cnt == -2) return l;
if (l.cnt == -1 && r.cnt == -1)
{
if (l.l == r.l) return fuck(l.l, l.l, -1);
else return fuck(l.l, r.l, 0);
}
else if (l.cnt == -1)
{
if (l.l == r.l) return r;
else return fuck(l.l, r.r, r.cnt + 1);
}
else if (r.cnt == -1)
{
if (l.r == r.l) return l;
else return fuck(l.l, r.l, l.cnt + 1);
}
else
{
return fuck(l.l, r.r, l.cnt + r.cnt + 2 - (l.r == r.l));
}
}
vector<int> out[100010];
int n, m, col[100010];
int fa[100010], depth[100010], weight[100010], wson[100010];
int dfn[100010], top[100010], id[100010], tot;
fuck tree[400010]; int lazy[400010];
fuck rev(const fuck &x)
{
return fuck(x.r, x.l, x.cnt);
}
void dfs1(int x)
{
weight[x] = 1, wson[x] = -1;
for (int i : out[x])
if (fa[x] != i)
{
fa[i] = x, depth[i] = depth[x] + 1;
dfs1(i);
weight[x] += weight[i];
if (wson[x] == -1 || weight[i] > weight[wson[x]]) wson[x] = i;
}
}
void dfs2(int x, int topf)
{
dfn[x] = ++tot, top[x] = topf, id[tot] = x;
if (wson[x] != -1)
{
dfs2(wson[x], topf);
for (int i : out[x])
if (i != fa[x] && i != wson[x])
dfs2(i, i);
}
}
void build(int x, int cl, int cr)
{
if (cl == cr)
{
tree[x] = fuck(col[id[cl]]);
return;
}
int mid = (cl + cr) / 2;
build(x * 2, cl, mid);
build(x * 2 + 1, mid + 1, cr);
tree[x] = tree[x * 2] * tree[x * 2 + 1];
}
void pushdown(int x)
{
if (lazy[x])
{
tree[x * 2] = tree[x * 2 + 1] = fuck(lazy[x]);
lazy[x * 2] = lazy[x * 2 + 1] = lazy[x];
lazy[x] = 0;
}
}
void chenge(int x, int cl, int cr, int L, int R, int col)
{
if (R < cl || cr < L) return;
if (L <= cl && cr <= R)
{
tree[x] = fuck(col);
lazy[x] = col;
return;
}
pushdown(x);
int mid = (cl + cr) / 2;
chenge(x * 2, cl, mid, L, R, col);
chenge(x * 2 + 1, mid + 1, cr, L, R, col);
tree[x] = tree[x * 2] * tree[x * 2 + 1];
}
fuck query(int x, int cl, int cr, int L, int R)
{
if (R < cl || cr < L) return fuck(0, 0, -2);
if (L <= cl && cr <= R) return tree[x];
pushdown(x);
int mid = (cl + cr) / 2;
return query(x * 2, cl, mid, L, R) * query(x * 2 + 1, mid + 1, cr, L, R);
}
int main()
{
freopen("paint.in", "r", stdin);
freopen("paint.out", "w", stdout);
scanf("%d%d", &n, &m);
for (int i = 1; i <= n; i++) scanf("%d", &col[i]);
for (int x, y, i = 1; i < n; i++) scanf("%d%d", &x, &y), out[x].push_back(y), out[y].push_back(x);
dfs1(1), dfs2(1, 1);
build(1, 1, n);
char ch;
for (int x, y, z, i = 1; i <= m; i++)
{
scanf(" %c%d%d", &ch, &x, &y);
if (ch == 'C')
{
scanf("%d", &z);
while (top[x] != top[y])
{
if (depth[top[x]] < depth[top[y]]) swap(x, y);
chenge(1, 1, n, dfn[top[x]], dfn[x], z);
x = fa[top[x]];
}
if (depth[x] > depth[y]) swap(x, y);
chenge(1, 1, n, dfn[x], dfn[y], z);
}
else
{
fuck ans1(0, 0, -2), ans2(0, 0, -2);
while (top[x] != top[y])
{
if (depth[top[x]] < depth[top[y]]) swap(x, y), swap(ans1, ans2);
ans1 = query(1, 1, n, dfn[top[x]], dfn[x]) * ans1;
x = fa[top[x]];
}
if (depth[x] > depth[y]) swap(x, y), swap(ans1, ans2);
fuck ans = rev(ans1) * query(1, 1, n, dfn[x], dfn[y]) * ans2;
printf("%d\n", ans.cnt + 2);
}
}
fclose(stdin);
fclose(stdout);
return 0;
}
luogu2486 [SDOI2011]染色的更多相关文章
- BZOJ 2243: [SDOI2011]染色 [树链剖分]
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6651 Solved: 2432[Submit][Status ...
- bzoj-2243 2243: [SDOI2011]染色(树链剖分)
题目链接: 2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 6267 Solved: 2291 Descript ...
- 【BZOJ2243】[SDOI2011]染色 树链剖分+线段树
[BZOJ2243][SDOI2011]染色 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询问节点a到节点b路径上的 ...
- bzoj2243:[SDOI2011]染色
链剖就可以了.一开始的想法错了.但也非常接近了.妈呀调的要死...然后把字体再缩小一号查错起来比较容易QAQ. #include<cstdio> #include<cstring&g ...
- bzoj 2243 [SDOI2011]染色(树链剖分,线段树)
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 4637 Solved: 1726[Submit][Status ...
- Bzoj 2243: [SDOI2011]染色 树链剖分,LCT,动态树
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 5020 Solved: 1872[Submit][Status ...
- 2243: [SDOI2011]染色
2243: [SDOI2011]染色 Time Limit: 20 Sec Memory Limit: 512 MBSubmit: 3113 Solved: 1204[Submit][Status ...
- bzoj 2243 [SDOI2011]染色(树链剖分+线段树合并)
[bzoj2243][SDOI2011]染色 2017年10月20日 Description 给定一棵有n个节点的无根树和m个操作,操作有2类: 1.将节点a到节点b路径上所有点都染成颜色c: 2.询 ...
- [SDOI2011]染色
[SDOI2011]染色 题目描述 输入输出格式 输出格式: 对于每个询问操作,输出一行答案. 解法 ps:这题本来是树剖的,但我用lct写的,以下是lct的写法,树剖会有所不同 我们考虑把不同色点的 ...
随机推荐
- 编译适用于TP-Link WR703N的OpenWRT固件
编译适用于TP-Link WR703N TP-Link MR11U 以及使用AR9331芯片组的单WAN/LAN复用口的路由. 注:刷机有风险,刷机需谨慎.一般情况下是不会失败的,若无法通过捅Rese ...
- 数据库:ubantu下MySQL安装指南
http://wiki.ubuntu.org.cn/MySQL%E5%AE%89%E8%A3%85%E6%8C%87%E5%8D%97 安装MySQL sudo apt-get install mys ...
- 【转】href="#"与"javascript:void(0);"的区别
在工作中,如果我们想把a标签中的链接置成空链接,我们一般会用两种方法: 1 <a href="#" target="_blank"></a&g ...
- DDD学习笔录——简介DDD的战术模式、问题空间和解空间
DDD的战术模式 DDD的战术模式(也称为模型构造块)是一个帮助创建 用于复杂有界上下文的有效模型的 模式集合. 也就是我们常说的设计模式. 问题空间 问题空间将问题域提炼成更多可管理的子域,是真对于 ...
- EmguCV3.0几个控件的使用
值方图(Histogram)是一种统计图数据,在影像处理中最常被用来统计一张图像或是感兴趣(ROI)区域的色彩分布,在这边本人使用的EmguCV 2.4.0版的内建值方图工具只有被包含在WinForm ...
- lineNumber: 8; columnNumber: 128; cvc-elt.1: 找不到元素 'beans' 的声明
转自:https://blog.csdn.net/java_yejun/article/details/51036638 spring和mybatis整合时出现了lineNumber: 8; colu ...
- Android Tombstone 分析
1.什么是tombstone 当一个动态库(native 程序)开始执行时,系统会注册一些连接到 debuggerd 的 signal handlers,当系统 crash 的时候,会保存一个 tom ...
- opencv 美白磨皮人脸检测<转>
1. 简介 这学期的计算机视觉课,我们组的课程项目为“照片自动美化”,其中我负责的模块为人脸检测与自动磨皮.功能为:用户上传一张照片,自动检测并定位出照片中的人脸,将照片中所有的人脸进行“磨皮”处理, ...
- DAY14-前端之Bootstrap框架
Bootstrap介绍 Bootstrap是Twitter开源的基于HTML.CSS.JavaScript的前端框架. 它是为实现快速开发Web应用程序而设计的一套前端工具包. 它支持响应式布局,并且 ...
- 并发之AtomicInteger
并发之AtomicInteger 1 java.util.concurrent.atomic概要 在java.util.concurrent.atomic包下存在着18个类,其中Integer ...