P3703 [SDOI2017]树点涂色
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]树点涂色的更多相关文章
- P3703 [SDOI2017]树点涂色 LCT维护颜色+线段树维护dfs序+倍增LCA
\(\color{#0066ff}{ 题目描述 }\) Bob有一棵\(n\)个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同. 定义一条路径的权值是:这条路径上的点 ...
- Luogu P3703 [SDOI2017]树点涂色
比较有趣的综合树上问题,刷LCT题单时做的但是发现后面LCT只是起了辅助作用233 首先我们分析每一个操作,\(1\)的定义就让我们联想到了access,我们回忆一下LCT的性质: LCT中每一个sp ...
- 洛谷P3703 [SDOI2017]树点涂色(LCT,dfn序,线段树,倍增LCA)
洛谷题目传送门 闲话 这是所有LCT题目中的一个异类. 之所以认为是LCT题目,是因为本题思路的瓶颈就在于如何去维护同颜色的点的集合. 只不过做着做着,感觉后来的思路(dfn序,线段树,LCA)似乎要 ...
- 并不对劲的bzoj4817:loj2001:p3703:[SDOI2017]树点涂色
题目大意 有一棵\(n\)(\(n\leq10^5\))个节点的树,每个点有颜色\(c\),一开始所有颜色互不相同 要进行\(m\)(\(m\leq10^5\))次操作,每次操作是以下三种中的一种: ...
- [Sdoi2017]树点涂色 [lct 线段树]
[Sdoi2017]树点涂色 题意:一棵有根树,支持x到根染成新颜色,求x到y颜色数,求x子树里点到根颜色数最大值 考场发现这个信息是可减的,但是没想到lct 特意设计成lct的形式! 如何求颜色数? ...
- 【LG3703】[SDOI2017]树点涂色
[LG3703][SDOI2017]树点涂色 题面 洛谷 题解 更博辣,更博辣!!! 猪年的第一篇博客 一次只能染根到\(x\),且染的颜色未出现过 这句话是我们解题的关键. 设\(x\)到根的颜色数 ...
- [BZOJ4817][SDOI2017]树点涂色(LCT+DFS序线段树)
4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 692 Solved: 408[Submit][Status ...
- 【BZOJ4817】[Sdoi2017]树点涂色 LCT+线段树
[BZOJ4817][Sdoi2017]树点涂色 Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路径的权值是:这条路 ...
- [Bzoj4817] [Sdoi2017]树点涂色 (LCT神题)
4817: [Sdoi2017]树点涂色 Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 629 Solved: 371[Submit][Status ...
随机推荐
- Windows 7系统启动MongoDB失败解决办法?
问题现象: 1.在配置Python环境安装MongoDB时发现在“服务”里面手动启动失败,报错如下: 2.在cmd里面也无法启动,注意这里要以管理员身份启动cmd哦 问题解决: 1.需要先在bin下执 ...
- 关于使用Entity Framework时遇到的问题 未找到具有固定名称“System.Data.SqlClient”的 ADO.NET 提供程序的实体框架提供程序。请确保在应用程序配置文件的“entityFramework”节中注册了该提供程序
问题描述: 使用Entity Framework获取数据时报以下错误: 未找到具有固定名称“System.Data.SqlClient”的 ADO.NET 提供程序的实体框架提供程序.请确保在应用程序 ...
- [翻译] NSRegexTester
NSRegexTester This is a very simple Mac OS X application that allows you to test regular expressions ...
- * args 和 **kwargs
def func(*args, **kwargs): print(args,kwargs) func("对", "哦",o=4, k=0) 结果---> ...
- C#基础学习之委托的理解和应用
委托的使用和语法定义 委托的使用是由四步来完成的,依次为:声明委托.创建委托对象.委托关联方法.调用 我们用一个例子来说明这四步如何操作,我们完成一个老板委托员工写报告的实例,看如何实现. 首先我们应 ...
- jquery validation验证身份证号、护照、电话号码、email
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...
- AOP的本质
AOP的本质是HOOK: HOOK的本质是:新函数包含原函数或新函数替换原函数: 需要解决的问题: 1.新函数的生成: 2.新函数的调用机制: 3.原函数的调用机制: 新函数的生成: 1.将已有的动态 ...
- BZOJ4180:字符串计数(SAM,二分,矩阵乘法)
Description SD有一名神犇叫做Oxer,他觉得字符串的题目都太水了,于是便出了一道题来虐蒟蒻yts1999. 他给出了一个字符串T,字符串T中有且仅有4种字符 'A', 'B', 'C', ...
- Hive学习之路 (十三)Hive分析窗口函数(一) SUM,AVG,MIN,MAX
数据准备 数据格式 cookie1,, cookie1,, cookie1,, cookie1,, cookie1,, cookie1,, cookie1,, 创建数据库及表 create datab ...
- 【转】HBase架构解析
转载地址:http://www.blogjava.net/DLevin/archive/2015/08/22/426877.html HBase架构组成 HBase采用Master/Slave架构搭建 ...