【bzoj3779】重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询
题目描述
输入
接下来n-1行,每行包含两个整数x和y,表示局域网中编号为x和y的计算机之间有网线直接相连。
接下来m行,每行包含一个操作或者询问,格式如问题描述中所述。
输出
样例输入
8 6
1 2
1 3
2 8
3 4
3 5
3 6
4 7
REQUEST 7
RELEASE 3
REQUEST 3
RECENTER 5
RELEASE 2
REQUEST 1
样例输出
4.0000000000
2.0000000000
1.3333333333
题解
LCT+树上倍增+DFS序+树状数组区间修改区间查询
这也是一道神题了。。。不查题解真的想不到。。。
首先同种颜色的一定是一条链。
然后如果把同种颜色的边看作实边,不同种颜色的边看作虚边的话,
一次感染就是LCT中的access操作,代价就是虚边数量+1。。。
(估计出题人是根据access操作的方法才出的这题吧。。。正常人根本想不到是LCT啊。。。)
一次RECENTER操作就是makeroot(makeroot自带一次access,就对应了题目的再感染一次。。。)
所以一个点的答案只与虚边数量有关,而只有虚边变化(access)时某些点的答案才会变化。
考虑加虚边答案怎么变化:一个点到其父亲节点加了一条虚边,那么其子树内所有节点到根节点都需要经过这一条虚边,该子树内答案+1。删虚边同理。
这里要注意一个问题:Splay的根节点不是这条链上深度最小的点,最左边的节点才是要更新子树的节点。因此在更新子树时还要找Splay中最左边的节点,同时不要忘了pushdown。
由于本题的根是变化的,因此参考 bzoj3083遥远的国度 ,将子树转化为dfs序上的至多两端区间,将得到的区间+1或-1。其中找第一个子节点的过程可以使用树上倍增实现。
因为本体略卡常,所以采用了树状数组区间修改区间查询,方法参考 bzoj3132上帝造题的七分钟 。
查询时同理,直接把区间和求出来即可。
时间复杂度$O(n\log^2n*不知多大的常数)=O(能过)$
#include <cstdio>
#include <algorithm>
#define N 100010
using namespace std;
typedef long long ll;
struct lct
{
int fa , c[2] , rev;
}a[N];
int n , head[N] , to[N << 1] , next[N << 1] , cnt , fa[N][20] , deep[N] , pos[N] , last[N] , tot , log[N] , root = 1;
ll f[N] , g[N];
char str[15];
inline void modify(int x , int a)
{
int i;
for(i = x ; i <= n ; i += i & -i) f[i] += a , g[i] += x * a;
}
inline ll query(int x)
{
int i;
ll s1 = 0 , s2 = 0;
for(i = x ; i ; i -= i & -i) s1 += f[i] , s2 += g[i];
return (x + 1) * s1 - s2;
}
inline void add(int x , int y)
{
to[++cnt] = y , next[cnt] = head[x] , head[x] = cnt;
}
void dfs(int x)
{
int i;
pos[x] = ++tot;
for(i = 1 ; (1 << i) <= deep[x] ; i ++ ) fa[x][i] = fa[fa[x][i - 1]][i - 1];
for(i = head[x] ; i ; i = next[i])
if(to[i] != fa[x][0])
fa[to[i]][0] = x , a[to[i]].fa = x , deep[to[i]] = deep[x] + 1 , dfs(to[i]);
last[x] = tot;
modify(pos[x] , 1) , modify(last[x] + 1 , -1);
}
inline int find(int x , int y)
{
int i;
for(i = log[deep[x] - deep[y]] ; ~i ; i -- )
if((1 << i) < deep[x] - deep[y])
x = fa[x][i];
return x;
}
inline void rever(int x)
{
swap(a[x].c[0] , a[x].c[1]) , a[x].rev ^= 1;
}
inline void pushdown(int x)
{
if(a[x].rev) rever(a[x].c[0]) , rever(a[x].c[1]) , a[x].rev = 0;
}
inline bool isroot(int x)
{
return a[a[x].fa].c[0] != x && a[a[x].fa].c[1] != x;
}
void update(int x)
{
if(!isroot(x)) update(a[x].fa);
pushdown(x);
}
inline void rotate(int x)
{
int y = a[x].fa , z = a[y].fa , l = (a[y].c[1] == x) , r = l ^ 1;
if(!isroot(y)) a[z].c[a[z].c[1] == y] = x;
a[x].fa = z , a[y].fa = x , a[a[x].c[r]].fa = y , a[y].c[l] = a[x].c[r] , a[x].c[r] = y;
}
inline void splay(int x)
{
int y , z;
update(x);
while(!isroot(x))
{
y = a[x].fa , z = a[y].fa;
if(!isroot(y)) rotate((a[y].c[0] == x) ^ (a[z].c[0] == y) ? x : y);
rotate(x);
}
}
inline void treemodify(int x , int v)
{
if(!x) return;
int y;
while(a[x].c[0]) pushdown(x) , x = a[x].c[0];
if(root == x) modify(1 , v);
else if(pos[root] < pos[x] || pos[root] > last[x]) modify(pos[x] , v) , modify(last[x] + 1 , -v);
else y = find(root , x) , modify(1 , v) , modify(pos[y] , -v) , modify(last[y] + 1 , v);
}
inline double treequery(int x)
{
int y;
if(root == x) return (double)query(n) / n;
else if(pos[root] < pos[x] || pos[root] > last[x]) return (double)(query(last[x]) - query(pos[x] - 1)) / (last[x] - pos[x] + 1);
else
{
y = find(root , x);
return (double)(query(n) - query(last[y]) + query(pos[y] - 1)) / (n - last[y] + pos[y] - 1);
}
}
inline void access(int x)
{
int t = 0 , y;
while(x) splay(x) , treemodify(t , -1) , y = a[x].c[1] , a[x].c[1] = t , treemodify(y , 1) , t = x , x = a[x].fa;
}
inline void makeroot(int x)
{
access(x) , splay(x) , rever(x) , root = x;
}
int main()
{
int m , i , x , y;
scanf("%d%d" , &n , &m);
for(i = 2 ; i <= n ; i ++ ) scanf("%d%d" , &x , &y) , add(x , y) , add(y , x) , log[i] = log[i >> 1] + 1;
dfs(1);
while(m -- )
{
scanf("%s%d" , str , &x);
if(str[2] == 'L') access(x);
else if(str[2] == 'C') makeroot(x);
else printf("%.10lf\n" , treequery(x));
}
return 0;
}
【bzoj3779】重组病毒 LCT+树上倍增+DFS序+树状数组区间修改区间查询的更多相关文章
- cf983E NN Country (倍增+dfs序+树状数组)
首先可以求出从某点做$2^k$次车能到的最浅的点,这个只要dfs一下,把它的孩子能到的最浅的点更新过来就可以 然后倍增地往上跳,不能跳到lca的上面,记录坐车的次数ans 此时有三种情况(设最远能跳到 ...
- bzoj 3779 重组病毒 —— LCT+树状数组(区间修改+区间查询)
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=3779 RELEASE操作可以对应LCT的 access,RECENTER则是 makeroo ...
- BZOJ4999 This Problem Is Too Simple!(树上差分+dfs序+树状数组)
对每个权值分别考虑.则只有单点加路径求和的操作.树上差分转化为求到根的路径和,子树加即可.再差分后bit即可.注意树上差分中根的父亲是0,已经忘了是第几次因为这个挂了. #include<ios ...
- 【bzoj4009】[HNOI2015]接水果 DFS序+树上倍增+整体二分+树状数组
题目描述 给出一棵n个点的树,给定m条路径,每条路径有一个权值.q次询问求一个路径包含的所有给定路径中权值第k小的. 输入 第一行三个数 n和P 和Q,表示树的大小和盘子的个数和水果的个数. 接下来n ...
- 【bzoj2819】Nim DFS序+树状数组+倍增LCA
题目描述 著名游戏设计师vfleaking,最近迷上了Nim.普通的Nim游戏为:两个人进行游戏,N堆石子,每回合可以取其中某一堆的任意多个,可以取完,但不可以不取.谁不能取谁输.这个游戏是有必胜策略 ...
- 【bzoj1146】[CTSC2008]网络管理Network 倍增LCA+dfs序+树状数组+主席树
题目描述 M公司是一个非常庞大的跨国公司,在许多国家都设有它的下属分支机构或部门.为了让分布在世界各地的N个部门之间协同工作,公司搭建了一个连接整个公司的通信网络.该网络的结构由N个路由器和N-1条高 ...
- HDU 5293 Tree chain problem 树形dp+dfs序+树状数组+LCA
题目链接: http://acm.hdu.edu.cn/showproblem.php?pid=5293 题意: 给你一些链,每条链都有自己的价值,求不相交不重合的链能够组成的最大价值. 题解: 树形 ...
- 【bzoj3881】[Coci2015]Divljak AC自动机+树链的并+DFS序+树状数组
题目描述 Alice有n个字符串S_1,S_2...S_n,Bob有一个字符串集合T,一开始集合是空的. 接下来会发生q个操作,操作有两种形式: “1 P”,Bob往自己的集合里添加了一个字符串P. ...
- 2018.10.20 NOIP模拟 巧克力(trie树+dfs序+树状数组)
传送门 好题啊. 考虑前面的32分,直接维护后缀trietrietrie树就行了. 如果#号不在字符串首? 只需要维护第一个#前面的字符串和最后一个#后面的字符串. 分开用两棵trie树并且维护第一棵 ...
随机推荐
- 九九乘法表(Python实现)
a = 1 #while实现 while a: b = 1 while b: print(str(b)+'*'+str(a),end='=') print(a*b,end=' ') if b == a ...
- java基础 UDP通信 user datagram protocol 用户数据豆协议 TCP transmission control protocol 传输控制协议 多线程TCP
无连接通信 UDP 客户端 package com.swift.test; import java.io.IOException; import java.net.DatagramPacket; im ...
- ios数据持久化--CoreData框架的介绍和使用
1.Core Data 是数据持久化存储的最佳方式 2.数据最终的存储类型可以是:SQLite数据库,XML,二进制,内存里,或自定义数据类型 在Mac OS X 10.5Leopard及以后的版本中 ...
- react的 react-router使用
官方API:https://reacttraining.com/react-router/web/api/BrowserRouter; React Router 安装命令如下. 使用时,路由器Rout ...
- 「译」setState如何知道它该做什么?
本文翻译自:How Does setState Know What to Do? 原作者:Dan Abramov 如果有任何版权问题,请联系shuirong1997@icloud.com 当你在组件中 ...
- JS之执行上下文
执行上下文(execution context),是JS中的一个很重要的概念.它对于我们理解函数定义,执行时都做了什么有着很大的意义.理解它我们才能明白我们常说的函数声明提升,作用域链,闭包等原理. ...
- ECSHOP快递物流单号查询插件
本ECSHOP快递物流单号跟踪插件提供国内外近2000家快递物流订单单号查询服务例如申通快递.顺丰快递.圆通快递.EMS快递.汇通快递.宅急送快递.德邦物流.百世快递.汇通快递.中通快递.天天快递等知 ...
- MLT教程:从BXL文件导入Altium Designer原理图封装和PCB封装
在TI官网的封装文件中提供弄BXL文件可以导出Altium Designer的封装库和原理图库. 这个界面往下面拉会看到: 然后可以下载各种封装的bxl文件了.下面视频说明bxl文件如何导出成功. 如 ...
- 使用windows live writer写cnblog-1 安装wlr
Writer:在本地编辑有声在色的博客内容,发布到你的网络博客! 离线安装文件下载地址:http://dx1.itopdog.cn/soft/wlsetup-all.rar 下了好几个离线版本的, ...
- UnicodeDecodeError: 'gbk' codec can't decode byte 0xab in position 11126: illegal multibyte sequence
python读取文件中含有中文时, 会报错: 解决办法是:打开文件时以utf-8格式打开,同样适用于gbk