P3703 [SDOI2017]树点涂色

链接

分析:

  首先对于询问,感觉是线段树维护dfs序,每个点记录到根的颜色个数。第二问差分,第三问区间取max。

  那么考虑修改,每次将一个点的颜色变成和父节点的颜色一样的过程中,这个点的子树内都会-1。

  这个修改的过程我们可以认为是修改边的过程,将一些边设为1,一些边设为0,那么一次修改对于一个点就是将原来1的边设为0,现在的边设为1。

  1和0类似lct中实边与虚边,所以可以lct维护当前那些边是1,那些是0。

  感觉跟个暴力似的,但是lct中access的操作是log的,所以修改的复杂度是log的,线段树中再有一个log,总复杂度是$O(nlog^2)$

代码:

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<iostream>
#include<cmath>
#include<cctype>
#include<set>
#include<queue>
#include<vector>
#include<map>
#define Root 1, n, 1
#define lson l, mid, rt << 1
#define rson mid + 1, r, rt << 1 | 1
using namespace std;
typedef long long LL; inline int read() {
int x=,f=;char ch=getchar();for(;!isdigit(ch);ch=getchar())if(ch=='-')f=-;
for(;isdigit(ch);ch=getchar())x=x*+ch-'';return x*f;
} const int N = , Log = ;
struct Edge{ int to, nxt; } e[N << ];
int head[N], f[N][], siz[N], pos[N], deth[N], Index, En, n, m; inline void add_edge(int u,int v) {
++En; e[En].to = v, e[En].nxt = head[u]; head[u] = En;
++En; e[En].to = u, e[En].nxt = head[v]; head[v] = En;
}
void dfs(int u) {
pos[u] = ++Index; siz[u] = ; deth[u] = deth[f[u][]] + ;
for (int i = head[u]; i; i = e[i].nxt) {
int v = e[i].to;
if (v == f[u][]) continue;
f[v][] = u;
dfs(v);
siz[u] += siz[v];
}
}
int LCA(int u,int v) {
if (deth[u] < deth[v]) swap(u, v);
int d = deth[u] - deth[v];
for (int j = Log; ~j; --j)
if ((d >> j) & ) u = f[u][j];
if (u == v) return u;
for (int j = Log; ~j; --j)
if (f[u][j] != f[v][j]) u = f[u][j], v = f[v][j];
return f[u][];
}
struct SegmentTree{
int mx[N << ], tag[N << ];
inline void pushup(int rt) { mx[rt] = max(mx[rt << ], mx[rt << | ]); }
inline void pushdown(int rt) {
mx[rt << ] += tag[rt]; mx[rt << | ] += tag[rt];
tag[rt << ] += tag[rt]; tag[rt << | ] += tag[rt];
tag[rt] = ;
}
void update(int l,int r,int rt,int L,int R,int v) {
if (L <= l && r <= R) { tag[rt] += v; mx[rt] += v; return ; }
if (tag[rt]) pushdown(rt);
int mid = (l + r) >> ;
if (L <= mid) update(lson, L, R, v);
if (R > mid) update(rson, L, R, v);
pushup(rt);
}
int query(int l,int r,int rt,int L,int R) {
if (L <= l && r <= R) return mx[rt];
if (tag[rt]) pushdown(rt);
int mid = (l + r) >> ;
if (R <= mid) return query(lson, L, R);
else if (L > mid) return query(rson, L, R);
else return max(query(lson, L, R), query(rson, L, R));
}
void pr(int l,int r,int rt) {
if (l == r) { cout << mx[rt] << " "; return ; }
if (tag[rt]) pushdown(rt);
int mid = (l + r) >> ;
pr(lson); pr(rson);
}
}T;
struct LCT{
int fa[N], ch[N][];
inline bool isroot(int x) { return ch[fa[x]][] != x && ch[fa[x]][] != x; }
inline int son(int x) { return ch[fa[x]][] == x; }
inline void rotate(int x) {
int y = fa[x], z = fa[y], c = son(y), b = son(x), a = ch[x][!b];
if (!isroot(y)) ch[z][c] = x; fa[x] = z;
ch[x][!b] = y; fa[y] = x;
ch[y][b] = a; if (a) fa[a] = y;
}
void splay(int x) {
while (!isroot(x)) {
int y = fa[x];
if (isroot(y)) rotate(x);
else {
if (son(x) == son(y)) rotate(y), rotate(x);
else rotate(x), rotate(x);
}
}
}
int find(int x) {
while (ch[x][]) x = ch[x][];
return x;
}
void access(int x) {
for (int last = , t; x; last = x, x = fa[x]) {
splay(x);
if (ch[x][]) t = find(ch[x][]), T.update(Root, pos[t], pos[t] + siz[t] - , ); // 这里找到原树上的位置
ch[x][] = last;
if (ch[x][]) t = find(ch[x][]), T.update(Root, pos[t], pos[t] + siz[t] - , -);
}
}
}lct;
int main() {
n = read(), m = read();
for (int i = ; i < n; ++i) {
int u = read(), v = read();
add_edge(u, v);
}
dfs();
for (int j = ; j <= Log; ++j)
for (int i = ; i <= n; ++i) f[i][j] = f[f[i][j - ]][j - ];
for (int i = ; i <= n; ++i) {
T.update(Root, pos[i], pos[i], deth[i]);
lct.fa[i] = f[i][];
}
while (m --) {
int opt = read(), x = read();
if (opt == ) lct.access(x);
else if (opt == ) {
int y = read(), z = LCA(x, y);
printf("%d\n", T.query(Root, pos[x], pos[x]) + T.query(Root, pos[y], pos[y]) - T.query(Root, pos[z], pos[z]) * + );
}
else {
printf("%d\n", T.query(Root, pos[x], pos[x] + siz[x] - ));
}
}
return ;
}

P3703 [SDOI2017]树点涂色的更多相关文章

  1. P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA

    \(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...

  2. Luogu P3703 [SDOI2017]树点涂色

    比较有趣的综合树上问题,刷LCT题单时做的但是发现后面LCT只是起了辅助作用233 首先我们分析每一个操作,\(1\)的定义就让我们联想到了access,我们回忆一下LCT的性质: LCT中每一个sp ...

  3. 洛谷P3703 [SDOI2017]树点涂色(LCT,dfn序,线段树,倍增LCA)

    洛谷题目传送门 闲话 这是所有LCT题目中的一个异类. 之所以认为是LCT题目,是因为本题思路的瓶颈就在于如何去维护同颜色的点的集合. 只不过做着做着,感觉后来的思路(dfn序,线段树,LCA)似乎要 ...

  4. 并不对劲的bzoj4817:loj2001:p3703:[SDOI2017]树点涂色

    题目大意 有一棵\(n\)(\(n\leq10^5\))个节点的树,每个点有颜色\(c\),一开始所有颜色互不相同 要进行\(m\)(\(m\leq10^5\))次操作,每次操作是以下三种中的一种: ...

  5. [Sdoi2017]树点涂色 [lct 线段树]

    [Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...

  6. 【LG3703】[SDOI2017]树点涂色

    [LG3703][SDOI2017]树点涂色 题面 洛谷 题解 更博辣,更博辣!!! 猪年的第一篇博客 一次只能染根到\(x\),且染的颜色未出现过 这句话是我们解题的关键. 设\(x\)到根的颜色数 ...

  7. [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 692  Solved: 408[Submit][Status ...

  8. 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树

    [BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...

  9. [Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)

    4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 629  Solved: 371[Submit][Status ...

随机推荐

  1. Oracle诊断工具 - ORA-2730x Troubleshooting Tool

    通常情况下,ORA-27300 ORA-27301 ORA-27302错误的原因是操作系统的系统调用错误或者操作系统配置问题,错误格式:ORA-27300: OS system dependent o ...

  2. sonar常见

    sonar在linux上安装好之后,若之后又更改了sonar的配置,则需要重启服务,重启方法如下: 1.进入到sonar的安装目录下,打开bin目录,会看到所有操作系统的文件夹 2.若操作系统为lin ...

  3. mysql二进制安装方法

    Linux centos7环境下MySQL安装教程 一.安装依赖包: a.boost_1_59_0下载:wget http://nchc.dl.sourceforge.net/project/boos ...

  4. redis几种数据类型以及使用场景

    1. string类型 string为最简单类型,一个key对应一个value set mykey "wangzai" ##设置key,第二次赋值会直接覆盖之前的 setnx my ...

  5. CDN高级技术专家周哲:深度剖析短视频分发过程中的用户体验优化技术点

    深圳云栖大会已经圆满落幕,在3月29日飞天技术汇-弹性计算.网络和CDN专场中,阿里云CDN高级技术专家周哲为我们带来了<海量短视频极速分发>的主题分享,带领我们从视频内容采集.上传.存储 ...

  6. python面试十题

    问题1: 请问如何修改以下python代码,使得下面的代码调用类A的show方法? class A(): def show(self): print("base show") cl ...

  7. linux面试总结

    一.填空题:1. 在Linux系统中,以 文件 方式访问设备 .2. Linux内核引导时,从文件 /etc/fstab 中读取要加载的文件系统.3. Linux文件系统中每个文件用 i节点 来标识. ...

  8. Oracle SQL Developer官方工具 初探

    查询表数据(打开工作表:Alt+F10) 运行SQL语句:(格式化:Ctrl+F7) 自动完成语句的设置 自动弹出的速度加快,并且将命中率提高,进行如下设置: 由于我的输入法占用了CTRL+,的快捷建 ...

  9. 囧啊!!时间戳转化为时间出错php

    最近写了一个api,测试也没发现啥问题.可是上线之后发现有时api的返回结果不正确.为什么呢? 调我接口的同学给了两个调用示例,理论上两个的结果应该一致,实际结果却不一致. api调用带了一个时间戳参 ...

  10. sql 模糊查询优化

    在sql语句中使用 like模糊查询时,应该尽量避免%%,因为模糊查询是比较慢的,当出现这样的情况时,应该考虑优化. 举个例子:我在表中查询2012 年创建的记录 SELECT * FROM `com ...