染色

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. c++实验3类和对象

     实 验 3: part 1:验证 part 2:graph #include <iostream> #include "graph.h" using namespac ...

  2. Get Error when restoring database in Sql Server 2008 R2

         When I restored a database I got an error: "The backup set holds a backup of a database ot ...

  3. 超强排序JavaScript插件

    Sortable:http://rubaxa.github.io/Sortable/

  4. TortoiseGit小乌龟 git管理工具

    1.新建分支git远端新建分支: b001本地git目录:右击--TortoiseGit--获取(会获取到新建分支) 2.本地新建分支对应远端分支本地新建分支:b001 关联远端分支b001(之后工作 ...

  5. linux中wget 、apt-get、yum rpm区别

    wget 类似于迅雷,是一种下载工具, 通过HTTP.HTTPS.FTP三个最常见的TCP/IP协议下载,并可以使用HTTP代理名字是World Wide Web”与“get”的结合. yum: 是r ...

  6. Python 3基础教程30-sys模块

    本文介绍sys模块,简单打印两个重定向输出. 目前使用机会没有,以后实际用到了,再去研究和学习.

  7. Spark性能超过Hadoop百倍

    Spark在偷换概念,Hadoop跑硬盘,Spark跑内存,地球人都知道,内存的速度可是远超硬盘一个量级,超过100倍又有什么奇怪的.如果要比,咱们都拿硬盘来跑跑看!

  8. 图的同构 (Graph Isomorphism)

    整理摘自:https://www.jianshu.com/p/c33b5d1b4cd9 同构是在数学对象之间定义的一类映射,它能揭示出在这些对象的属性或者操作之间存在的关系.若这两个数学结构之间存在同 ...

  9. Daily Scrum02 12.01

    今天是2013年12月的第一天,希望大家都有一个新的开始,一起努力!     Member Today's Task Tomorrow's Task 李孟 Task 856: 熟悉单元测试方法熟悉单元 ...

  10. SpringBoot 中使用shiro注解使之生效

    在shiroConfig配置类中增加如下代码: /** * 开启Shiro的注解(如@RequiresRoles,@RequiresPermissions),需借助SpringAOP扫描使用Shiro ...