染色

Time Limit: 20 Sec  Memory Limit: 256 MB

Description

  

Input

  

Output

  

Sample Input

  13
  0 1
  0 2
  1 11
  1 10
  1 9
  9 12
  2 5
  5 8
  2 4
  2 3
  4 6
  4 7
  7
  q 0
  O 4
  q 6
  q 2
  O 9
  q 9
  q 2

Sample Output

  2.0000000000
  1.0000000000
  0.8571428571
  0.5000000000
  1.8571428571

HINT

  

Main idea

  询问x到根路径上不同颜色的个数,支持将x到根的路径上的点全部设为新的颜色。

Solution

  我们将边两端的点颜色相同的边设为实边不同的设为虚边。那么一次新增颜色的操作显然就是LCT的access操作!access的时候恰是虚边和实边的转换。

  那么我们只要用线段树维护每个点到根的贡献,结合dfs序来实现子树加,每次在LCT进行access的时候进行+-1修改,然后询问的时候用区间求和求得答案即可。

Code

 #include<iostream>
#include<string>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<ctime>
#include<cmath>
using namespace std;
typedef long long s64;
const int ONE=; int n,m,x,y;
int pos[ONE],size[ONE],Dep[ONE],dfn[ONE],cnt;
s64 res;
char ch[]; int lc[ONE],rc[ONE],fa[ONE]; int get()
{
int res=,Q=;char c;
while( (c=getchar())< || c> )
if(c=='-')Q=-;
res=c-;
while( (c=getchar())>= && c<= )
res=res*+c-;
return res*Q;
} namespace tree
{
int next[ONE],first[ONE],go[ONE],tot; void Add(int u,int v)
{
next[++tot]=first[u]; first[u]=tot; go[tot]=v;
next[++tot]=first[v]; first[v]=tot; go[tot]=u;
} void Dfs(int u,int father)
{
pos[u] = ++cnt; dfn[cnt] = u;
size[u] = ;
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(v==father) continue;
Dep[v] = Dep[u] + ;
fa[v] = u;
Dfs(v,u);
size[u] += size[v];
}
}
} namespace Seg
{
struct power
{
s64 add,value;
}Node[ONE]; void pushdown(int i,int Q)
{
if(Node[i].add)
{
Node[i<<].add+=Node[i].add;
Node[i<<|].add+=Node[i].add;
Node[i<<].value+=Node[i].add*(Q-Q/);
Node[i<<|].value+=Node[i].add*(Q/);
Node[i].add=;
}
} void Build(int i,int l,int r)
{
if(l==r)
{
Node[i].value = Dep[dfn[l]];
return;
}
int mid=(l+r)>>;
Build(i<<,l,mid); Build(i<<|,mid+,r);
Node[i].value=Node[i<<].value+Node[i<<|].value;
} void Update(int i,int l,int r,int L,int R,int x)
{
if(L<=l && r<=R)
{
Node[i].add+=x;
Node[i].value+=(s64)(r-l+)*x;
return;
} pushdown(i,r-l+);
int mid=(l+r)>>;
if(L<=mid) Update(i<<,l,mid,L,R,x);
if(mid+<=R) Update(i<<|,mid+,r,L,R,x);
Node[i].value=Node[i<<].value+Node[i<<|].value;
} void Query(int i,int l,int r,int L,int R)
{
if(L<=l && r<=R)
{
res+=Node[i].value;
return;
}
pushdown(i,r-l+);
int mid=(l+r)>>;
if(L<=mid) Query(i<<,l,mid,L,R);
if(mid+<=R) Query(i<<|,mid+,r,L,R);
}
} namespace LCT
{
int is_real(int x)
{
return (lc[fa[x]]==x || rc[fa[x]]==x);
} void Turn(int x)
{
int y=fa[x],z=fa[y];
int b= x==lc[y] ? rc[x]:lc[x]; fa[x]=z; fa[y]=x;
if(b) fa[b]=y; if(z)
{
if(y==lc[z]) lc[z]=x;
else
if(y==rc[z]) rc[z]=x;
} if(x==lc[y]) rc[x]=y,lc[y]=b;
else lc[x]=y,rc[y]=b;
} void Splay(int x)
{
while(is_real(x))
{
if(is_real(fa[x]))
{
if( (lc[fa[x]]==x) == (lc[fa[fa[x]]]==fa[x]) ) Turn(fa[x]);
else Turn(x);
}
Turn(x);
}
} int find_root(int x)
{
while(lc[x]) x=lc[x];
return x;
} void access(int x)
{
for(int p=x,q=; p; q=p,p=fa[p])
{
Splay(p);
if(rc[p])
{
int N=find_root(rc[p]);
Seg::Update(,,n,pos[N],pos[N]+size[N]-,+);
}
rc[p]=q;
if(rc[p])
{
int N=find_root(rc[p]);
Seg::Update(,,n,pos[N],pos[N]+size[N]-,-);
}
}
}
} int main()
{
n=get();
for(int i=;i<n;i++)
{
x=get(); y=get();
x++; y++;
tree::Add(x,y);
}
tree::Dfs(,);
Seg::Build(,,n); m=get();
while(m--)
{
scanf("%s",ch); x=get(); x++;
if(ch[]=='O')
{
LCT::access(x);
}
else
{
res=;
Seg::Query(,,n,pos[x],pos[x]+size[x]-);
printf("%.10lf\n",(double)res/size[x]);
}
} }

【Foreign】染色 [LCT][线段树]的更多相关文章

  1. 3.28 省选模拟赛 染色 LCT+线段树

    发现和SDOI2017树点涂色差不多 但是当时这道题模拟赛的时候不会写 赛后也没及时订正 所以这场模拟赛的这道题虽然秒想到了LCT和线段树但是最终还是只是打了暴力. 痛定思痛 还是要把这道题给补了. ...

  2. 【SDOI2017】树点染色【线段树+LCT】

    本来只是想练练LCT,没想到是个线段树 对于操作1:诶新的颜色?这不是access吗? 也就是说,我们用一棵splay来表示一种颜色 操作2直接在LCT上乱搞-- 不对啊,操作3要查子树 诶好像是静态 ...

  3. bzoj4817 & loj2001 [Sdoi2017]树点涂色 LCT + 线段树

    题目传送门 https://lydsy.com/JudgeOnline/problem.php?id=4817 https://loj.ac/problem/2001 题解 可以发现这个题就是 bzo ...

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

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

  5. BZOJ4817[Sdoi2017]树点涂色——LCT+线段树

    题目描述 Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色.Bob可能会进 ...

  6. 【BZOJ4817】【SDOI2017】树点涂色 [LCT][线段树]

    树点涂色 Time Limit: 10 Sec  Memory Limit: 128 MB[Submit][Status][Discuss] Description Bob有一棵n个点的有根树,其中1 ...

  7. 【bzoj4817】树点涂色 LCT+线段树+dfs序

    Description Bob有一棵n个点的有根树,其中1号点是根节点.Bob在每个点上涂了颜色,并且每个点上的颜色不同.定义一条路 径的权值是:这条路径上的点(包括起点和终点)共有多少种不同的颜色. ...

  8. BZOJ 3779 重组病毒 LCT+线段树(维护DFS序)

    原题干(由于是权限题我就直接砸出原题干了,要看题意概述的话在下面): Description 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力 ...

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

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

随机推荐

  1. 源码解析:解析掌阅X2C 框架

    前言 掌阅出品了X2C 框架,听说可以加快性能.喜欢研究源码的我,肯定要来看下是怎么回事. 作为一个开发,应该不屑于只会使用开源框架. OK,来尝试下. 项目地址: https://github.co ...

  2. jetbraints激活码

    G91XMO9AVI-eyJsaWNlbnNlSWQiOiJHOTFYTU85QVZJIiwibGljZW5zZWVOYW1lIjoic29uZyB3YW5nIiwiYXNzaWduZWVOYW1lI ...

  3. 今天领导分享了一个探测端口的命令-linux下提示bash:command not found

    今天领导分享了一个探测端口的命令,于是试了一下,提示未找到-bash: nc: command not found  因此决定将bash的命令在复习一下,温故而知新 总结整理于此: 确定你的DNS可以 ...

  4. javac一次性编译多个包下的.java文件

    如题是我想要知道的,然后在网上搜了一下 下面是在某些帖子里看到别人说的只言片语 =========================================================== ...

  5. 【vim环境配置】解决ubuntu上 由YouCompleteMe插件配置不当引起的 自动补全失效的问题

    背景: 由于不可抗拒的原因,学习环境由之前centos的一台机器上,变成了ubuntu的一台机器上.因此,需要在新的ubuntu的机器上再配置一次vim环境.算起来这已经是第三次配置vim环境了(ma ...

  6. mysql 处理日期格式

    DATE_FORMAT(createTime,'%Y-%m-%d %H:%i:%s') 对应格式: 2018-12-17 17:33:43 DATE_FORMAT()函数所有格式:   以后有需要在自 ...

  7. 「日常训练」 Soldier and Traveling (CFR304D2E)

    题意 (CodeForces 546E) 对一个无向图,给出图的情况与各个节点的人数/目标人数.每个节点的人只可以待在自己的城市或走到与他相邻的节点. 问最后是否有解,输出一可行解(我以为是必须和答案 ...

  8. Pro Git - 笔记2

    Git Basics Getting a Git Repository Initializing a Repository in an Existing Directory For Linux: $ ...

  9. PTA实验报告 数组

    (第二张代码均为英红的代码) 题目1:题目名称:数组元素循环右移问题 1. 本题PTA提交列表 2. 设计思路(包括流程图) 将数组内每个位置移动,第2个放第一个,第三个放第二个,以此类推.使用两个循 ...

  10. Good Time 冲刺 三

    第三天 日期:2018.6.16 一.今日完成任务情况及遇到的问题 王怡镔:继续在学习微信小程序的设计,完善设计发现页面,开始编写发现页面 于鑫宇:配合黄鹤的工作,学习端口相关知 胡雅馨:继续改进优化 ...