【注意事项】

为了体现增强版,题目限制和数据范围有所增强:

时间限制:1.5s

内存限制:128MB

对于15% 的数据,1<=N,Q<=1000.

对于35% 的数据,1<=N,Q<=10000.

对于50% 的数据,1<=N,Q<=100000,且数据均为官方数据.

对于100% 的数据,1<=N,Q<=1000000.

请注意常数因子对于程序运行的影响。

  并查集很简单,并查集就是倒序处理,表示删除一个点的标记,删除后不会再加回来,删完后,合并当前点与其father的集合,根为father的原来的根,具体看代码……

 #include <iostream>
#include <cstring>
#include <cstdlib>
#include <cstdio>
using namespace std;
const int N=;
int cnt,fir[N],to[N*],nxt[N*];
void addedge(int a,int b){
nxt[++cnt]=fir[a];
to[fir[a]=cnt]=b;
}
int fa[N],vis[N],pre[N];
int qr[N],tp[N],ans[N];
void DFS(int x){
for(int i=fir[x];i;i=nxt[i])
if(to[i]!=pre[x]){
pre[to[i]]=x;
DFS(to[i]);
}
}
void DFS(int x,int f){
fa[x]=f;
for(int i=fir[x];i;i=nxt[i])
if(to[i]!=pre[x]){
if(!vis[to[i]])DFS(to[i],f);
else DFS(to[i],to[i]);
}
}
int Find(int x){return fa[x]==x?x:fa[x]=Find(fa[x]);}
int n,Q;char op[];
int main(){
freopen("tree++.in","r",stdin);
freopen("tree++.out","w",stdout);
int sz=<<;
char*p=(char*)malloc(sz)+sz;
__asm__("movl %0,%%esp\n"::"r"(p));
scanf("%d%d",&n,&Q);
for(int i=,a,b;i<n;i++){
scanf("%d%d",&a,&b);
addedge(a,b);
addedge(b,a);
}DFS();
for(int i=;i<=Q;i++){
scanf("%s%d",op,&qr[i]);
tp[i]=op[]=='Q'?:;
}
vis[]=;
for(int i=;i<=Q;i++)
if(tp[i])vis[qr[i]]+=;
DFS(,);
for(int i=Q;i>=;i--){
if(!tp[i])
ans[i]=Find(qr[i]);
else{
if(!--vis[qr[i]]){
int x=qr[i];
fa[x]=Find(pre[x]);
}
}
}
for(int i=;i<=Q;i++)
if(!tp[i])printf("%d\n",ans[i]);
return ;
}

  树链剖分很好想,但慢了些。

 #include <iostream>
#include <cstring>
#include <cstdio>
#include <cstdlib>
#include <ctime>
using namespace std;
const int N=;
int cnt,fir[N],nxt[N*],to[N*];
void addedge(int a,int b){
nxt[++cnt]=fir[a];to[fir[a]=cnt]=b;
nxt[++cnt]=fir[b];to[fir[b]=cnt]=a;
}
int sz[N],son[N],fa[N],dep[N];
void DFS(int x){sz[x]=;
for(int i=fir[x];i;i=nxt[i])
if(to[i]!=fa[x]){
dep[to[i]]=dep[fa[to[i]]=x]+;
DFS(to[i]);sz[x]+=sz[to[i]];
if(sz[son[x]]<sz[to[i]])son[x]=to[i];
}
}
int tot,id[N],rid[N],top[N];
void DFS(int x,int tp){
top[rid[id[x]=++tot]=x]=tp;
if(son[x])DFS(son[x],tp);
for(int i=fir[x];i;i=nxt[i])
if(to[i]!=fa[x]&&to[i]!=son[x])
DFS(to[i],to[i]);
}
int sum[N*],pos[N*];
#define mid (l+r>>1)
void Push_up(int x){
sum[x]=sum[x<<]+sum[x<<|];
if(sum[x]==)pos[x]=;
if(sum[x<<|])pos[x]=pos[x<<|];
else pos[x]=pos[x<<];
}
void Update(int x,int l,int r,int g){
if(l==r){pos[x]=rid[l];sum[x]+=;return;}
if(mid>=g)Update(x<<,l,mid,g);
else Update(x<<|,mid+,r,g);
Push_up(x);
} int Query(int x,int l,int r,int a,int b){
//if(!sum[x])return 0;
if(l>=a&&r<=b)return pos[x];int ret=;
if(mid<b)ret=Query(x<<|,mid+,r,a,b);
if(!ret&&mid>=a)ret=Query(x<<,l,mid,a,b);
return ret;
} int tag[N],n,Q,x;
int Solve(int x){
while(x){
int d=Query(,,n,id[top[x]],id[x]);
if(d)return d;x=fa[top[x]];
}
return ;
}
char op[],c;
void read(int &x){
x=;while(c=getchar(),c>''||c<'');
while(x=x*+(c^),c=getchar(),c>=''&&c<='');
}
int main(){
freopen("tree++.in","r",stdin);
freopen("tree++.out","w",stdout);
read(n);read(Q);
int size = << ; // 256MB
char *p = (char*)malloc(size) + size;
__asm__("movl %0, %%esp\n" :: "r"(p));
for(int i=,a,b;i<n;i++){
read(a);read(b);
addedge(a,b);
}
DFS();DFS(,);
Update(,,n,);tag[]=;
while(Q--){
scanf("%s",op);read(x);
if(op[]=='C'){
if(tag[x])continue;
Update(,,n,id[x]);
tag[x]=;
}
else{
printf("%d\n",Solve(x));
}
}
//printf("%.2f\n",1.0*clock()/CLOCKS_PER_SEC);
return ;
}

数据结构(并查集||树链剖分):HEOI 2016 tree的更多相关文章

  1. 洛谷P4092 [HEOI2016/TJOI2016]树 并查集/树链剖分+线段树

    正解:并查集/树链剖分+线段树 解题报告: 传送门 感觉并查集的那个方法挺妙的,,,刚好又要复习下树剖了,所以就写个题解好了QwQ 首先说下并查集的方法趴QwQ 首先离线,读入所有操作,然后dfs遍历 ...

  2. 并查集+树链剖分+线段树 HDOJ 5458 Stability(稳定性)

    题目链接 题意: 有n个点m条边的无向图,有环还有重边,a到b的稳定性的定义是有多少条边,单独删去会使a和b不连通.有两种操作: 1. 删去a到b的一条边 2. 询问a到b的稳定性 思路: 首先删边考 ...

  3. 2019西北工业大学程序设计创新实践基地春季选拔赛 I Chino with Rewrite (并查集+树链剖分+线段树)

    链接:https://ac.nowcoder.com/acm/contest/553/I 思路:离线整棵树,用并查集维护下联通的情况,因为值只有60个,用2的x(1<=x<=60)次方表示 ...

  4. 【BZOJ3626】LCA(树链剖分,Link-Cut Tree)

    [BZOJ3626]LCA(树链剖分,Link-Cut Tree) 题面 Description 给出一个n个节点的有根树(编号为0到n-1,根节点为0).一个点的深度定义为这个节点到根的距离+1. ...

  5. 【BZOJ2157】旅游(树链剖分,Link-Cut Tree)

    [BZOJ2157]旅游(树链剖分,Link-Cut Tree) 题面 Description Ray 乐忠于旅游,这次他来到了T 城.T 城是一个水上城市,一共有 N 个景点,有些景点之间会用一座桥 ...

  6. 洛谷P4482 [BJWC2018]Border 的四种求法 字符串,SAM,线段树合并,线段树,树链剖分,DSU on Tree

    原文链接https://www.cnblogs.com/zhouzhendong/p/LuoguP4482.html 题意 给定一个字符串 S,有 q 次询问,每次给定两个数 L,R ,求 S[L.. ...

  7. 【NOI复习】树链剖分

    简介 树链剖分通常用来解决一类维护静态树上路径信息的问题, 例如:给定一棵点带权树, 接下来每次操作会修改某条路径上所有点的权值(修改为同一个值或是同加上一个值等) , 以及询问某条路径上所有点的权值 ...

  8. 树链剖分 (求LCA,第K祖先,轻重链剖分、长链剖分)

      2020/4/30   15:55 树链剖分是一种十分实用的树的方法,用来处理LCA等祖先问题,以及对一棵树上的节点进行批量修改.权值和查询等有奇效. So, what is 树链剖分? 可以简单 ...

  9. HDU 5458 Stability (树链剖分+并查集+set)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=5458 给你n个点,m条边,q个操作,操作1是删边,操作2是问u到v之间的割边有多少条. 这题要倒着做才 ...

随机推荐

  1. 24、Javascript BOM

    BOM(Browser Object Model)浏览器对象模型,一组浏览器提供的API. window对象 window对象表示当前浏览器的窗口,是Javascript的顶级对象,所有创建的对象.函 ...

  2. TransactionScope简单用法

    记录TransactionScope简单用法,示例如下: void Test() { using (TransactionScope scope = new TransactionScope()) { ...

  3. Asp.Net MVC Ajax

    将ASP.NET MVC中的form提交改为ajax提交 在ASP.NET MVC视图中通过 @using (Html.BeginForm()) 产生的是form表单提交代码,可以用javascrip ...

  4. js使用

    js使用 HTML 中的脚本必须位于 <script> 与 </script> 标签之间. 脚本可被放置在 HTML 页面的 <body> 和 <head&g ...

  5. 如何在 Debian / Ubuntu 服务器上架设 L2TP / IPSec VPN

    本站的 Rio 最近在一台 Ubuntu 和一台 Debian 主机上配置了 L2TP / IPSec VPN,并在自己的博客上做了记录.原文以英文写就,我把它大致翻译了一下,结合我和 Rio 在设置 ...

  6. (三)Struts2 拦截器

    所有的学习我们必须先搭建好Struts2的环境(1.导入对应的jar包,2.web.xml,3.struts.xml) 第一节:拦截器简介 (百度百科Struts2) Struts2 拦截器是在访问某 ...

  7. 读懂IL代码(四)

    这一篇是IL系列的最后一篇的,主要是要说一下IL中的流程控制.我相信,经过前面三篇的介绍,看IL代码应该不是什么大问题了吧.好吧,闲话不多说了,就来简单的说一下吧. 还是跟前几篇一样,以例子来解释说明 ...

  8. (转) c# ExecuteNonQuery() 返回值 -1

    这是之前我遇到问题,在网上找解决方法时找到的,当时复制到txt文档了,今天整理笔记又看到了,贴出来,便于以后查阅.原文的作者没记住~~ 查询某个表中是否有数据的时候,如果用ExecuteNonQuer ...

  9. JavaScript Iframe富文本编辑器中的光标定位

    最近在项目中碰到一个比较棘手的问题: 在iframe富文本编辑器中,有个工具栏,这个工具栏在iframe标签之外,工具栏上有一个按钮,点击该按钮向iframe正在编辑中的光标处插入一个图片,图片会插入 ...

  10. Application_Start

    这个时间是在第一次访问网站的时候触发..比如你发布了一个网站,,我第一个来访问,,就会触发这个事件..以后再有人来访问就不会触发了.. 一般的,我们总是以为Application_Start是一个应用 ...