题目

在2016年,佳媛姐姐刚刚学习了树,非常开心。现在他想解决这样一个问题:给定一颗有根树(根为1),有以下

两种操作:1. 标记操作:对某个结点打上标记(在最开始,只有结点1有标记,其他结点均无标记,而且对于某个

结点,可以打多次标记。)2. 询问操作:询问某个结点最近的一个打了标记的祖先(这个结点本身也算自己的祖

先)你能帮帮他吗?

分析

此题有很多种方法

暴力+并查集

转了别人的

考虑离线处理。

我们将所有的操作倒序处理,利用并查集进行维护。对于一个修改操

作(即失去标记),相当于将这一联通块块与它父亲的联通块合并。对于

一个查询操作,直接查询所在的块的父亲即可。

实现中有些细节需要注意,比如每个点可能会被标记多次,所以要以

最早的被标记时间做为“失去标记”的时间。

时间复杂度为O(n + qα(n))

DFN序+线段树

首先搞一遍dfn序,

接着发现,在用一棵子树中,dfn序都是相邻的。

好了,线段树修改查询。

树链剖分

单独修改、查询1到num的路径。

裸题一枚。

#include <cmath>
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#include <queue>
const int maxlongint=2147483647;
const int mo=1000000007;
const int N=100005;
using namespace std;
int tree[N*6],top[N],d[N],size[N],deep[N],son[N],fa[N],n,m,tot,ans;
int last[N*2],next[N*2],to[N*2],bef[N],aft[N];
void bj(int x,int y)
{
next[++tot]=last[x];
last[x]=tot;
to[tot]=y;
}
void dg(int x,int y)
{
size[x]=1;
int mx=0;
for(int i=last[x];i;i=next[i])
{
int j=to[i];
if(j!=y)
{
deep[j]=deep[x]+1;
fa[j]=x;
dg(j,x);
size[x]+=size[j];
if(size[j]>mx)
{
mx=size[j];
son[x]=j;
}
}
}
}
int dg1(int x,int y)
{
d[++tot]=x;
aft[x]=tot;
bef[tot]=x;
if(!top[x])
top[x]=x;
if(son[x])
{
top[son[x]]=top[x];
dg1(son[x],x);
}
for(int i=last[x];i;i=next[i])
{
int j=to[i];
if(j!=y && j!=son[x])
{
dg1(j,x);
}
}
}
int put(int v,int l,int r,int x)
{
if(l==r)
{
tree[v]=bef[x];
return 0;
}
int mid=(l+r)/2;
if(x<=mid)
{
put(v*2,l,mid,x);
}
else
put(v*2+1,mid+1,r,x);
tree[v]=deep[tree[v*2]]>deep[tree[v*2+1]]?tree[v*2]:tree[v*2+1];
}
int find(int v,int l,int r,int x,int y)
{
if(l==x && r==y)
{
ans=deep[ans]>deep[tree[v]]?ans:tree[v];
return 0;
}
int mid=(l+r)/2;
if(y<=mid)
{
find(v*2,l,mid,x,y);
}
else
if(mid<x)
{
find(v*2+1,mid+1,r,x,y);
}
else
{
find(v*2,l,mid,x,mid);
find(v*2+1,mid+1,r,mid+1,y);
}
tree[v]=deep[tree[v*2]]>deep[tree[v*2+1]]?tree[v*2]:tree[v*2+1];
}
int main()
{
freopen("4604.in","r",stdin);
freopen("4604.out","w",stdout);
scanf("%d%d",&n,&m);
for(int i=1;i<=n-1;i++)
{
int x,y;
scanf("%d%d",&x,&y);
bj(x,y);
bj(y,x);
}
deep[1]=1;
dg(1,0);
top[1]=1;
tot=0;
dg1(1,0);
put(1,1,n,aft[1]);
scanf("\n");
for(int i=1;i<=m;i++)
{
int c;
int x,y;
c=getchar();
while((c!='Q')&&(c!='C'))c=getchar();
scanf("%d\n",&x);
if(c=='C')
{
put(1,1,n,aft[x]);
}
else
{
ans=0;
while(top[x]!=top[1])
{
find(1,1,n,aft[top[x]],aft[x]);
x=fa[top[x]];
}
find(1,1,n,aft[1],aft[x]);
printf("%d\n",ans);
}
}
}

【bzoj4551】【NOIP2016模拟7.11】树的更多相关文章

  1. NOIP2016模拟赛三 Problem B: 神奇的树

    题面 Description 有一棵神奇的树.这棵树有N个节点,在每个节点上都有宝藏,每个宝藏价值V[i]金币:对于每条边,每经过一次都要花费C[i]金币. 值得注意的是,每个宝藏只能领取一次(也可以 ...

  2. JZOJ 4611. 【NOI2016模拟7.11】接水问题 (贪心+A*+可持久化线段树)

    Description: https://gmoj.net/senior/#main/show/4611 题解: 先把A从大到小排序,最小的由排序不等式显然. 考虑类似第k短路的A*的做法. 定义状态 ...

  3. 「考试」noip模拟9,11,13

    9.1 辣鸡 可以把答案分成 每个矩形内部连线 和 矩形之间的连线 两部分 前半部分即为\(2(w-1)(h-1)\),后半部分可以模拟求(就是讨论四种相邻的情况) 如果\(n^2\)选择暴力模拟是有 ...

  4. vue 模拟下拉树

    // 使用vue 做表格部分其他部分暂不修改 var app = new Vue({ el: "#freightTbl", watch: { //监听表格数据的变化[使用 watc ...

  5. [转载]如何在C++03中模拟C++11的右值引用std::move特性

    本文摘自: http://adamcavendish.is-programmer.com/posts/38190.htm 引言 众所周知,C++11 的新特性中有一个非常重要的特性,那就是 rvalu ...

  6. 串门赛: NOIP2016模拟赛——By Marvolo 丢脸记

    前几天liu_runda来机房颓废,顺便扔给我们一个网址,说这上面有模拟赛,让我们感兴趣的去打一打.一开始还是没打算去看一下的,但是听std说好多人都打,想了一下,还是打一打吧,打着玩,然后就丢脸了. ...

  7. 6424. 【NOIP2019模拟2019.11.13】我的订书机之恋

    题目描述 Description Input Output Sample Input 见下载 Sample Output 见下载 Data Constraint 题解 lj题卡线段树 求出每个右端点往 ...

  8. [CSP-S模拟测试]:砍树(数学+模拟)

    题目传送门(内部题1) 输入格式 第一行两个整数$n$,$k$,代表树苗的数量和最大看书的总长度.第二行n个整数$a_i$,代表林先森希望每棵树苗的最终高度. 输出格式 一行一个整数,代表最大可能的d ...

  9. 2019.8.1 NOIP模拟测试11 反思总结

    延迟了一天来补一个反思总结 急匆匆赶回来考试,我们这边大家的状态都稍微有一点差,不过最后的成绩总体来看好像还不错XD 其实这次拿分的大都是暴力[?],除了某些专注于某道题的人以及远程爆踩我们的某学车神 ...

随机推荐

  1. jest 提示 Unexpected identifier 的解决方案

    概述 今天在玩 jest 的时候,发现用 import 就会报 Unexpected identifier 的错误.查了很久的资料,最后终于解决了. 参考资料:Jest tests can't pro ...

  2. Win7上防火墙开放FTP服务以及ping解决方案

    1.windows 防火墙开放ftp服务 The following 4 steps will allow both non-secure and SSL FTP traffic through fi ...

  3. 手动搭建redis cluster

    集群中至少应该有奇数个节点,所以至少有三个节点,每个节点至少有一个备份节点,所以下面使用6节点(主节点.备份节点由redis-cluster集群确定) 1.安装redis节点指定端口解压redis压缩 ...

  4. Centos 安装 FTP

    安装教程:   基于 CentOS 搭建 FTP 文件服务 搭建完成后,使用windows文件夹访问FTP报错,请确保输入的文件名是否正确,并且您有权访问此文件. 先确认ftp服务正常 修改:   设 ...

  5. Matlab——矩阵运算 矩阵基本变换操作

    矩阵运算 + 加 - 减 .* 乘 ./ 左除 .\ 右除 .^ 次方 .' 转置 除了加减符号,其余的运算符必须加“.” >> a = : a = >> a- %减法 ans ...

  6. 【MM系列】SAP 的账期分析和操作

    公众号:SAP Technical 本文作者:matinal 原文出处:http://www.cnblogs.com/SAPmatinal/ 原文链接:[MM系列]SAP 的账期分析和操作   前言部 ...

  7. idea中dbug模式的使用

    1:进入断点状态时候每个按钮的用途如图: 2:当运行过得代码需要查看输出内容时候,可以选中需要查看的代码进行运行如图:会在控制台输出选中代码执行的结果

  8. python 并发编程 多进程 JoinableQueue

    JoinableQueue和Queue 使用一样 这就像是一个Queue对象,但队列允许项目的使用者通知生成者项目已经被成功处理.通知进程是使用共享的信号和条件变量来实现的. JoinableQueu ...

  9. jmeter正则提取器提取指定位置的字符串

    1.需求:提取登录后的凭证ticket供系统其他接口调用 2.登录接口返回的格式如下: { "ret_code":0, "ret_msg":"logi ...

  10. adb,aapt等命令使用

    adb         install/uninstall:安装/卸载手机中的应用.         devices:查看当前连接到电脑中的设备. adb shell         首先运行adb ...