【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树并且维护第一棵 ...
随机推荐
- 基于mybatis设计简单OA系统问题1
全类名与全路径 全类名是某个文件在项目中的位置,格式为包名.类名 路径分为相对路径和绝对路径. 绝对路径是指这个文件在操作系统中的位置, 相对路径通过这个文件的上一级 ./ 或下一级/ 来指定文件 ...
- percona-zabbix-templates插件安装监控MySQL
前期准备:被监控机已经安装好php 1.在zabbix客户端安装mysql监控插件rpm包 rpm -ivh https://www.percona.com/downloads/percona-mon ...
- 路由器基础配置之单臂路由实现vlan间通信
我们将以上面的拓扑图开始进行配置,目的为设置单臂路由实现vlan间通信,设置4个vlan,pc0,1,2为vlan10 pc3,4,5为vlan20:pc6,7,8为vlan30:server0,1为 ...
- VM12虚拟机安装os x 10.11系统以及注意事项
一.安装步骤 原文链接:https://blog.csdn.net/soachenshui/article/details/49251513 https://blog.csdn.net/soachen ...
- 用 js 写一个获取随机颜色的程序
function getColor(){ var color="#"; for(var i=0;i<6;i++){ color+=(Math.random()*16 | 0) ...
- php-5.6.26源代码 - 扩展模块的种类,扩展模块的执行埋点
模块种类(两种) 类型一:zend的模块:(类似zend_extension=test.so) 识别方法: php.ini中以zend_extension开头的配置,如zend_extension=t ...
- Laravel系列之CMS系统学习 — 角色、权限配置【1】
一.后台Admin模块 后台管理是有管理员的,甚至超级管理员,所以在设计数据表的时候,就会有2个方案,一个方案是共用users数据表,添加is_admin,is_superAdmin字段来进行验证,或 ...
- 准备篇(三)Makefile
Makefile 也是蛮多的, 嵌入式的Makefile也是很重要的,所以单独开一个分支.
- 零基础~仿qq登录界面
html代码: <!DOCTYPE html> <html> <head> <meta charset="utf-8"> <t ...
- 剑指Offer - 九度1283 - 第一个只出现一次的字符
剑指Offer - 九度1283 - 第一个只出现一次的字符2013-11-21 21:13 题目描述: 在一个字符串(1<=字符串长度<=10000,全部由大写字母组成)中找到第一个只出 ...