3306: 树

Time Limit: 10 Sec  Memory Limit: 256 MB
Submit:
792  Solved: 262
[Submit][Status][Discuss]

Description

给定一棵大小为 n 的有根点权树,支持以下操作:

  • 换根
  • 修改点权 
     • 查询子树最小值

Input

  第一行两个整数 n, Q
,分别表示树的大小和操作数。
  接下来n行,每行两个整数f,v,第i+1行的两个数表示点i的父亲和点i的权。保证f < i。如 果f =
0,那么i为根。输入数据保证只有i = 1时,f = 0。
  接下来 m 行,为以下格式中的一种:
  • V x y表示把点x的权改为y

  • E x 表示把有根树的根改为点 x
  • Q x 表示查询点 x 的子树最小值

Output

  对于每个 Q
,输出子树最小值。

Sample Input

3 7
0 1
1 2
1 3
Q
1
V 1 6
Q 1
V 2 5
Q 1
V 3 4
Q 1

Sample Output

1
2
3
4

HINT

  对于 100% 的数据:n, Q ≤ 10^5。

Source

Solution

有道很类似的题目,不过是树链修改

那道题去要树链剖分,而这里只需要线段树维护一下DFS序即可

先以1为根做DFS和建线段树维护dfs序

换根操作只需要讨论一下:

若root=x,那么显然查询全树min

若LCA(root,x)!=x,那么显然毫无影响

若LCA(root,x)==x,那么发现对答案产生了影响,除了x-->root的那个子树,其余都变成了x的子树,那么我们倍增出那个不属于的子树中最接近x的节点,然后统计不包含这棵子树的答案即可

Code

#include<iostream>
#include<cstdio>
#include<cstring>
#include<cmath>
#include<algorithm>
using namespace std;
int read()
{
int x=,f=; char ch=getchar();
while (ch<'' || ch>'') {if (ch=='-') f=-; ch=getchar();}
while (ch>='' && ch<='') {x=x*+ch-''; ch=getchar();}
return x*f;
}
#define MAXN 100010
int N,Q,val[MAXN];
struct EdgeNode{int next,to;}edge[MAXN<<];
int head[MAXN],cnt;
void AddEdge(int u,int v) {cnt++; edge[cnt].next=head[u]; head[u]=cnt; edge[cnt].to=v;}
void InsertEdge(int u,int v) {if (u==) return; AddEdge(u,v); AddEdge(v,u);}
int pl[MAXN],dfn,pr[MAXN],dfsn[MAXN],deep[MAXN],father[MAXN][],root;
void DFS(int now,int last)
{
pl[now]=++dfn; dfsn[dfn]=now;
for (int i=; i<=; i++)
if (deep[now]>=(<<i))
father[now][i]=father[father[now][i-]][i-];
else
break;
for (int i=head[now]; i; i=edge[i].next)
if (edge[i].to!=last)
{
deep[edge[i].to]=deep[now]+;
father[edge[i].to][]=now;
DFS(edge[i].to,now);
}
pr[now]=dfn;
}
int LCA(int x,int y)
{
if (deep[x]<deep[y]) swap(x,y);
int dd=deep[x]-deep[y];
for (int i=; i<=; i++)
if (dd&(<<i)) x=father[x][i];
for (int i=; i>=; i--)
if (father[x][i]!=father[y][i])
x=father[x][i],y=father[y][i];
if (x==y) return x; else return father[x][];
}
struct SegmentTreeNode{int l,r,minn;}tree[MAXN<<];
inline void Update(int now) {tree[now].minn=min(tree[now<<].minn,tree[now<<|].minn);}
void BuildTree(int now,int l,int r)
{
tree[now].l=l; tree[now].r=r;
if (l==r) {tree[now].minn=val[dfsn[l]]; return;}
int mid=(l+r)>>;
BuildTree(now<<,l,mid);
BuildTree(now<<|,mid+,r);
Update(now);
}
void Change(int now,int pos,int D)
{
int l=tree[now].l,r=tree[now].r;
if (l==r) {tree[now].minn=D; return;}
int mid=(l+r)>>;
if (pos<=mid) Change(now<<,pos,D);
else Change(now<<|,pos,D);
Update(now);
}
int Query(int now,int L,int R)
{
if (R<L) return 0x7fffffff;
int l=tree[now].l,r=tree[now].r;
if (L==l && R==r) return tree[now].minn;
int mid=(l+r)>>,re=0x7fffffff;
if (R<=mid) return Query(now<<,L,R);
else if (L>mid) return Query(now<<|,L,R);
else return min(Query(now<<,L,mid),Query(now<<|,mid+,R));
return re;
}
void ChangeRoot(int x) {root=x;}
int GetAns(int x)
{
int lca=LCA(root,x);
if (x==root) return Query(,,N);
if (pl[x]<=pl[root] && pr[x]>=pr[root])
{
int dd=deep[root]-deep[x]-,y=root;
for (int i=; i<=; i++)
if (dd&(<<i)) y=father[y][i];
return min(Query(,,pl[y]-),Query(,pr[y]+,dfn));
}
return Query(,pl[x],pr[x]);
}
int main()
{
N=read(); Q=read();
for (int fa,i=; i<=N; i++) fa=read(),InsertEdge(fa,i),val[i]=read();
DFS(,); root=;
BuildTree(,,dfn);
while (Q--)
{
char opt[]; scanf("%s",opt+);
int x,y;
switch (opt[])
{
case 'V' : x=read(),y=read(); Change(,pl[x],y); break;
case 'E' : x=read(); ChangeRoot(x); break;
case 'Q' : x=read(); printf("%d\n",GetAns(x)); break;
}
}
return ;
}

【BZOJ-3306】树 线段树 + DFS序的更多相关文章

  1. BZOJ.2434.[NOI2011]阿狸的打字机(AC自动机 树状数组 DFS序)

    题目链接 首先不需要存储每个字符串,可以将所有输入的字符依次存进Trie树,对于每个'P',记录该串结束的位置在哪,以及当前节点对应的是第几个串(当前串即根节点到当前节点):对于'B',只需向上跳一个 ...

  2. 【BZOJ】2434: [Noi2011]阿狸的打字机 AC自动机+树状数组+DFS序

    [题意]阿狸喜欢收藏各种稀奇古怪的东西,最近他淘到一台老式的打字机.打字机上只有28个按键,分别印有26个小写英文字母和'B'.'P'两个字母. 经阿狸研究发现,这个打字机是这样工作的: l 输入小写 ...

  3. luogu SP8093 后缀自动机+树状数组+dfs序

    这题解法很多,简单说几个: 1. 线段树合并,时间复杂度是 $O(nlog^2n)$ 的. 2. 暴力跳 $fail,$ 时间复杂度 $O(n\sqrt n),$ 比较暴力. 3. 建立后缀树后在 $ ...

  4. BZOJ.4184.shallot(线段树分治 线性基)

    BZOJ 裸的线段树分治+线性基,就是跑的巨慢_(:з」∠)_ . 不知道他们都写的什么=-= //41652kb 11920ms #include <map> #include < ...

  5. [BZOJ 4025]二分图(线段树分治+带边权并查集)

    [BZOJ 4025]二分图(线段树分治+带边权并查集) 题面 给出一个n个点m条边的图,每条边会在时间s到t出现,问每个时间的图是否为一个二分图 \(n,m,\max(t_i) \leq 10^5\ ...

  6. BZOJ 4285 使者 (CDQ分治+dfs序)

    题目传送门 题目大意:给你一棵树,有三种操作,在两个点之间连一个传送门,拆毁一个已有的传送门,询问两个点之间的合法路径数量.一条合法路径满足 1.经过且仅经过一个传送门 2.不经过起点终点简单路径上的 ...

  7. 浅谈树套树(线段树套平衡树)&学习笔记

    0XFF 前言 *如果本文有不好的地方,请在下方评论区提出,Qiuly感激不尽! 0X1F 这个东西有啥用? 树套树------线段树套平衡树,可以用于解决待修改区间\(K\)大的问题,当然也可以用 ...

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

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

  9. BZOJ 4034"树上操作"(DFS序+线段树)

    传送门 •题意 有一棵点数为 N 的树,以点 1 为根,且树点有边权. 然后有 M 个操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的 ...

随机推荐

  1. c语言:printf系列的函数

    /** *----------------------------stdio.h--------------------------------------- * int printf(const c ...

  2. sqlserver 通用分页存储过程

    来源:http://www.jb51.net/article/19936.htm CREATE PROCEDURE commonPagination ), --要显示的列名,用逗号隔开 ), --要查 ...

  3. IE6/IE7/IE8/Firefox/Chrome/Safari的CSS hack兼容一览表

    浏览器兼容问题一直是前段开发工程师比较头痛的问题,熟悉了里面的规则也就变得简单了,这里有一份资料可以分享给大家,大家平时开发过程中遵循这个规律的话,会变得轻松多了: 各浏览器CSS hack兼容表: ...

  4. topshelf包装redis为windows服务

    topshelf包装redis为windows服务 Redis服务端目前用的是控制台程序运行,部署的时候能作为windows服务后台运行感觉更好.找到一篇文章Running Redis as a Wi ...

  5. Python之线程、进程和协程

    python之线程.进程和协程 目录: 引言 一.线程 1.1 普通的多线程 1.2 自定义线程类 1.3 线程锁 1.3.1 未使用锁 1.3.2 普通锁Lock和RLock 1.3.3 信号量(S ...

  6. Android -- Apk安装简诉

    安装涉及到如下几个目录 system/app  ​ 系统自带的应用程序,无法删除 data/app   用户程序安装的目录,有删除权限. 安装时把apk文件复制到此目录 ​ data/data  存放 ...

  7. 爱春秋之戏说春秋 Writeup

    爱春秋之戏说春秋 Writeup 第一关 图穷匕见 这一关关键是给了一个图片,将图片下载到本地后,打开以及查看属性均无任何发现,尝试把图片转换为.txt格式.在文本的最后发现这样一串有规律的代码: 形 ...

  8. SQL基础之数据库

    1.基础概念 首先要强调一点,就是我们的数据库是由数据库系统来管理的,我们登入数据库并在其上进行操作时最终均要通过数据库系统来完成.可以理解成在数据库上进行操作的是客户端,数据库系统是服务端.一个数据 ...

  9. 反射 实现不同模型相同属性赋值 第二集(automapper)

    前言: 两年前写过一个 反射实现不同模型相同属性赋值 只能简单的实现两个model 相同属性名,相同类型赋值 最近又遇到这个问题,需要对相同属性名或者指定属性名 不同类型(复杂对象,如:List< ...

  10. js的几种排序

    转载:http://www.jb51.net/article/81520.htm 一.冒泡排序 ? 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 ...