\[SDOI2017 树点染色
\]

  • 题目描述

    Bob 有一棵 $ n $ 个点的有根树,其中 $ 1 $ 号点是根节点。Bob 在每个节点上涂了颜色,并且每个点上的颜色不同。

    定义一条路径的权值是,这条路径上的点(包括起点和终点)共有多少种不同的颜色。

    Bob 可能会进行这几种操作:

  • $ 1 \ x $,把点 $ x $ 到根节点的路径上的所有的点染上一种没有用过的新颜色;

  • $ 2 \ x \ y $,求 $ x $ 到 $ y $ 的路径的权值;

  • $ 3 \ x $,在以 $ x $ 为根的子树中选择一个点,使得这个点到根节点的路径权值最大,求最大权值。

  • Bob 一共会进行 $ m $ 次操作。

  • 样例输入输出

input
5 6
1 2
2 3
3 4
3 5
2 4 5
3 3
1 4
2 4 5
1 5
2 4 5 output
3
4
2
2
  • 数据范围

    \(n \leq 10^5,m \leq 10^5\)

  • 题解

    考虑定义\(fa(x)\)如果\(x\)与父节点颜色相同就是1,否则为0,强行定义\(fa(1) = 1\)

    几率\(dis(x)\)表示从\(x\)到1路径所有的\(fa(x)\)的和,那么就是路径权值。

    操作1需要你支持一系列\(fa(x)\)的修改,并且同时维护\(dis(x)\)

    操作2访问\(x,y\)答案就是\(dis(x) + dis(y) - (2 \times (dis(lca))) + 1\)

    操作3求最大的\(dis(x)\)

    操作1可以通过\(LCT\)的\(Access\)操作实现。

    操作2和3可以用链剖+线段树维护信息。

    总评,数据结构板题。

#include <bits/stdc++.h>
using namespace std;
const int N=100010;
int n,m,tot,cnt,Next[N<<1],head[N],tree[N<<1],Fa[N],fa[N],dep[N],size[N],Son[N],tid[N],NUM[N],top[N],Max[N*4],lazy[N*4],son[N][2];
void add(int x,int y)
{
tot++;
Next[tot]=head[x];
head[x]=tot;
tree[tot]=y;
}
void dfs(int u,int father,int depth)
{
Fa[u]=fa[u]=father;dep[u]=depth;size[u]=1;Son[u]=0;
int maxsize=0;
for (int i=head[u];i;i=Next[i])
{
int v=tree[i];
if (v==fa[u]) continue;
dfs(v,u,depth+1);
size[u]+=size[v];
if (size[v]>maxsize)
{
maxsize=size[v];
Son[u]=v;
}
}
}
void dfs1(int u,int ancestor)
{
tid[u]=++cnt;NUM[cnt]=u;top[u]=ancestor;
if (Son[u]) dfs1(Son[u],ancestor);
for (int i=head[u];i;i=Next[i])
if (tree[i]!=fa[u]&&tree[i]!=Son[u]) dfs1(tree[i],tree[i]);
}
void build(int l,int r,int id)
{
if (l==r) { Max[id]=dep[NUM[l]];return;}
int mid=(l+r)>>1;
build(l,mid,id<<1);
build(mid+1,r,id<<1|1);
Max[id]=max(Max[id<<1],Max[id<<1|1]);
}
void down(int id)
{
if (lazy[id]!=0)
{
Max[id<<1]+=lazy[id];
Max[id<<1|1]+=lazy[id];
lazy[id<<1]+=lazy[id];
lazy[id<<1|1]+=lazy[id];
lazy[id]=0;
}
}
void change(int l,int r,int id,int x,int y,int d)
{
if (l>y||r<x) return;
if (l!=r) down(id);
if (x<=l&&r<=y)
{
Max[id]+=d;
lazy[id]+=d;
return;
}
int mid=(l+r)>>1;
change(l,mid,id<<1,x,y,d);
change(mid+1,r,id<<1|1,x,y,d);
Max[id]=max(Max[id<<1],Max[id<<1|1]);
}
int query_max(int l,int r,int id,int x,int y)
{
if (l>y||r<x) return 0;
if (l!=r) down(id);
if (x<=l&&r<=y) return Max[id];
int mid=(l+r)>>1;
return max(query_max(l,mid,id<<1,x,y),query_max(mid+1,r,id<<1|1,x,y));
}
int query_sum(int l,int r,int id,int x)
{
if (l>x||r<x) return 0;
if (l!=r) down(id);
if (l==r&&l==x) return Max[id];
int mid=(l+r)>>1;
return query_sum(l,mid,id<<1,x)+query_sum(mid+1,r,id<<1|1,x);
}
int LCA(int x,int y)
{
while (top[x]!=top[y])
{
if (dep[top[x]]<dep[top[y]]) swap(x,y);
x=Fa[top[x]];
}
if (dep[x]>dep[y]) swap(x,y);
return x;
}
int Query(int x)
{
return query_sum(1,n,1,tid[x]);
}
inline bool isRoot(int x) { return (son[fa[x]][0]!=x)&&(son[fa[x]][1]!=x);}
inline void Rotate(int x)
{
int y=fa[x],z=fa[y],l,r;
if (son[y][0]==x) l=0;else l=1;
r=l^1;
if (!isRoot(y))
{
if (son[z][0]==y) son[z][0]=x;else son[z][1]=x;
}
fa[x]=z;fa[y]=x;fa[son[x][r]]=y;
son[y][l]=son[x][r];son[x][r]=y;
}
inline void splay(int x)
{
while (!isRoot(x))
{
int y=fa[x],z=fa[y];
if (!isRoot(y))
{
if ((son[z][0]==y)^(son[y][0]==x)) Rotate(x);
else Rotate(y);
}
Rotate(x);
}
}
inline void access(int x)
{
for (int i=0;x;i=x,x=fa[x])
{
splay(x);
if (son[x][1])
{
int id=son[x][1];
while (son[id][0]) id=son[id][0];
change(1,n,1,tid[id],tid[id]+size[id]-1,1);
}
if (i)
{
int id=i;
while (son[id][0]) id=son[id][0];
change(1,n,1,tid[id],tid[id]+size[id]-1,-1);
}
son[x][1]=i;
}
}
int main()
{
scanf("%d%d",&n,&m);
tot=cnt=0;
for (int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
add(x,y);add(y,x);
}
dfs(1,0,1);
dfs1(1,1);
build(1,n,1);
while (m--)
{
int id,x,y;
scanf("%d",&id);
if (id==1) { scanf("%d",&x);access(x);}
if (id==2) { scanf("%d%d",&x,&y);printf("%d\n",Query(x)+Query(y)-Query(LCA(x,y))*2+1);}
if (id==3) { scanf("%d",&x);printf("%d\n",query_max(1,n,1,tid[x],tid[x]+size[x]-1));}
}
return 0;
}

SDOI2017 树点染色的更多相关文章

  1. loj2001[SDOI2017]树点染色

    题意:给你一棵树,一开始每个点上的颜色互不相同.三种操作:op1:x到根的路径上的点都染上一种新的颜色.op2:设一条路径的权值为val(x,y),求x到y路径的val.op3:询问x的子树中最大的到 ...

  2. SDOI2017树点染色

    题目链接 发现1操作很像lct中的access,然后它每次染的又是一个新颜色,因此同一个颜色就在同一颗splay里了,且一个点到根的权值val[i]也就是到根路径上虚边的个数,然后看access时会对 ...

  3. 洛谷3703 [SDOI2017] 树点染色 【LCT】【线段树】

    题目分析: 操作一很明显等价于LCT上的access操作,操作二是常识,操作三转化到dfs序上求最大值也是常识.access的时候顺便在线段树中把对应部分-1,把右子树的子树+1即可. 代码: #in ...

  4. codevs 5963 [SDOI2017]树点染色

     [题解]: #include<cstdio> #include<cstring> #include<iostream> using namespace std; ...

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

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

  6. P3703 [SDOI2017]树点涂色

    P3703 [SDOI2017]树点涂色 链接 分析: 首先对于询问,感觉是线段树维护dfs序,每个点记录到根的颜色个数.第二问差分,第三问区间取max. 那么考虑修改,每次将一个点的颜色变成和父节点 ...

  7. codevs 1191 树轴染色 线段树区间定值,求和

    codevs 1191 树轴染色 Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://www.codevs.cn/problem/1191/ Des ...

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

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

  9. HDU3974 Assign the task(多叉树转换为线段+线段树区间染色)

    题目大意:有n个人,给你他们的关系(老板和员工),没有直属上司的人就是整个公司的领导者,这意味着n个人形成一棵树(多叉树).当一个人被分配工作时他会让他的下属也做同样的工作(并且立即停止手头正在做的工 ...

随机推荐

  1. webpack 兼容低版本浏览器,转换ES6 ES7语法

    ES6,ES7真的太棒了,async +await+Promise,让我阅读代码的时候不用再从左拉到右了(异步太多,一层套一层真的太头痛) 但是有个问题,打包后低版本浏览器运行不了,还有我用了一些混淆 ...

  2. percona-toolkit工具包的安装和初步使用

    percona-toolkit工具包的安装和初步使用 原文地址:http://blog.csdn.net/yumushui/article/details/42919601 一.percona-too ...

  3. SqlSession(SqlSessionTemplate类) 实现Mybatis

    yBatis3与spring整合之使用SqlSession(SqlSessionDaoTemplate类) ---------- 注:这是手工编写实现的方式(其实可以直接使用注入映射器的) SqlSe ...

  4. 十二、SpringBoot 优雅的集成Spring Security

    前言 至于什么是Spring security ,主要两个作用,用户认证和授权.即我们常说的,用户只有登录了才能进行其他操作,没有登录的话就重定向到登录界面.有的用户有权限执行某一操作,而有的用户不能 ...

  5. JQuery Mobile 图片布局

    JQuery Mobile 图片布局 1.实现效果

  6. C++构造函数异常(二)

    继续上一篇文章提到的构造异常话题,下面继续谈另外两个场景,即多继承构造异常,以及智能指针构造异常 第3:对多继承当中,某个基类构造异常,而其他基类已构造成功,则构造成功的基类不会析构,由编译器负责回收 ...

  7. 运维02 Shell基础命令(一)

    Shell基础命令(一)   Shell 教程 Shell 是一个用 C 语言编写的程序,它是用户使用 Linux 的桥梁.Shell 既是一种命令语言,又是一种程序设计语言. Shell 是指一种应 ...

  8. mysql三种连接方式

    sql四种连接方式demo: 表a 表b a.id与b.parent_id有关系 1.内连接:SELECT a.*,b.* from a INNER JOIN b ON a.id=b.parent_i ...

  9. Msys2升级后不能编译

    Msys2升级后不能编译 */--> code {color: #FF0000} pre.src {background-color: #002b36; color: #839496;} cod ...

  10. c# PID算法入门

    离开工控行业已经有一段时间了,最近回忆起以前的工作,又对 PID 算法有了兴趣.所以写了一个小项目,希望可以帮到需要的人,也算是对那段工作经历的一个总结. 这是一个 winform 的项目.负载是一个 ...