题目

题目大意

给你一棵树,接下来对这棵树进行三种操作:

1、询问两点之间的距离。

2、让某个点变为它原来的第\(h\)个祖先的最后一个儿子。

3、求\(dfs\)序中最后一个深度为\(k\)的点。


正解

第一种是Cold_Chair大爷提出来的\(LCT\)维护\(ETT\)的做法。

具体怎样就不说了……据说代码5000+

第二种就直接是\(ETT\)了(其实这是一道ETT的板题啊)

对于入栈点(记作\(l\))打个\(+1\),对于出栈点(记作\(r\))打个\(-1\),维护前缀和。这个前缀和相当于深度。

这里维护前缀和的方法比较巧妙,不需要区间修改,具体见程序。

对于第一个操作,找到\(l_u\)和\(l_v\)之间最小的深度。显然这个深度就是它们的\(LCA\)的深度。

对于第二个操作,找第\(h\)个祖先的时候先求出祖先的深度,然后在前面找最靠右的深度为它的点。显然前缀和是连续的,所以可以在\(splay\)上二分。如果它是入栈点,就是要找的那个祖先;如果是出栈点,那它的父亲就是那个祖先。

对于第三个操作,直接找最后面前缀和为\(k\)的点。和操作二一样。


代码

using namespace std;
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <ctime>
#include <cstdlib>
#include <climits>
#include <vector>
#define N 100010
#define INF 1000000000
int n,m;
vector<int> to[N];
struct Node *null,*root;
struct Node{
Node *fa,*c[2];
int val,sum,mx,mn;
inline void init(int _val){
fa=c[0]=c[1]=null;
val=sum=mx=mn=_val;
}
inline void update(){
sum=c[0]->sum+c[1]->sum+val;
mx=max(max(c[0]->mx,c[0]->sum+val+c[1]->mx),c[0]->sum+val);
mn=min(min(c[0]->mn,c[0]->sum+val+c[1]->mn),c[0]->sum+val);
}
inline bool getson(){return fa->c[0]!=this;}
inline void rotate(){
Node *y=fa,*z=y->fa;
if (z!=null)
z->c[y->getson()]=this;
bool k=getson();
fa=z;
y->c[k]=c[k^1],c[k^1]->fa=y;
c[k^1]=y,y->fa=this;
sum=y->sum,mx=y->mx,mn=y->mn;
y->update();
}
inline void splay(Node *t){
while (fa!=t){
if (fa->fa!=t)
getson()!=fa->getson()?rotate():fa->rotate();
rotate();
}
if (t==null)
root=this;
}
} in[N],out[N],*beg,*end;
inline Node *nxt(Node *t,bool dir){
t->splay(null);
Node *res=t->c[dir];
for (;res->c[dir^1]!=null;res=res->c[dir^1]);
return res;
}
inline void push_back(Node *x){
Node *t=root;
for (;t->c[1]!=null;t=t->c[1]);
t->splay(null);
t->c[1]=x,x->fa=t;
t->update();
}
inline Node *split(Node *l,Node *r){
l=nxt(l,0),r=nxt(r,1);
r->splay(null),l->splay(r);
Node *t=l->c[1];
l->c[1]=null,t->fa=null;
l->update(),r->update();
return t;
}
inline void insert(Node *t,Node *p){
p->splay(null);
Node *pre=nxt(p,0);
pre->splay(p);
pre->c[1]=t,t->fa=pre;
pre->update(),p->update();
}
inline Node *find_last(Node *t,int k){
t->splay(null);
Node *x=t->c[0],*res=null;
while (1){
if (x->c[1]!=null && x->c[1]->mn<=k-x->c[0]->sum-x->val && k-x->c[0]->sum-x->val<=x->c[1]->mx){
k-=x->c[0]->sum+x->val;
x=x->c[1];
continue;
}
else if (x->c[0]->sum+x->val==k)
return x;
x=x->c[0];
}
return res;
}
void dfs(int x){
in[x].init(1);
push_back(&in[x]);
for (int i=0;i<to[x].size();++i)
dfs(to[x][i]);
out[x].init(-1);
push_back(&out[x]);
}
int fa[N];
int main(){
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i){
int num;
scanf("%d",&num);
for (int j=0;j<num;++j){
int x;
scanf("%d",&x);
to[i].push_back(x);
fa[x]=i;
}
}
null=new Node,*null={null,null,null,0,0,-INF,INF};
beg=new Node,beg->init(0),root=beg;
dfs(1);
end=new Node,end->init(0),push_back(end);
for (int i=1;i<=m;++i){
int op;
scanf("%d",&op);
if (op==1){
int u,v,depu,depv,deplca;
scanf("%d%d",&u,&v);
if (u==v){
printf("0\n");
continue;
}
in[u].splay(null),in[v].splay(&in[u]);
if (in[v].getson()==0)
swap(u,v);
Node *l=nxt(&in[u],0),*r=nxt(&in[v],1);
r->splay(null),l->splay(r);
deplca=l->c[0]->sum+l->val+l->c[1]->mn;
depu=l->c[0]->sum+l->val+1;
depv=l->sum;
printf("%d\n",depu+depv-deplca*2);
}
else if (op==2){
int v,h,anc;
scanf("%d%d",&v,&h);
in[v].splay(null);
Node *tmp=find_last(&in[v],in[v].c[0]->sum+1-h);
fa[v]=anc=(tmp->val==-1?fa[tmp-out]:tmp-in);
Node *t=split(&in[v],&out[v]);
insert(t,&out[anc]);
}
else{
int k;
scanf("%d",&k);
Node *tmp=find_last(end,k+1);
printf("%d\n",tmp->val==-1?fa[tmp-out]:tmp-in);
}
}
return 0;
}

总结

\(LCT\)搞不了的东西,要试试\(ETT\)。

[JZOJ3691] 【CF414E】Mashmokh's Designed tree的更多相关文章

  1. 【BZOJ2959】长跑(Link-Cut Tree,并查集)

    [BZOJ2959]长跑(Link-Cut Tree,并查集) 题面 BZOJ 题解 如果保证不出现环的话 妥妥的\(LCT\)傻逼题 现在可能会出现环 环有什么影响? 那就可以沿着环把所有点全部走一 ...

  2. 【BZOJ2588】Count On a Tree(主席树)

    [BZOJ2588]Count On a Tree(主席树) 题面 题目描述 给定一棵N个节点的树,每个点有一个权值,对于M个询问(u,v,k),你需要回答u xor lastans和v这两个节点间第 ...

  3. 【BZOJ2816】【ZJOI2012】网络(Link-Cut Tree)

    [BZOJ2816][ZJOI2012]网络(Link-Cut Tree) 题面 题目描述 有一个无向图G,每个点有个权值,每条边有一个颜色.这个无向图满足以下两个条件: 对于任意节点连出去的边中,相 ...

  4. 【CF434E】Furukawa Nagisa's Tree 点分治

    [CF434E]Furukawa Nagisa's Tree 题意:一棵n个点的树,点有点权.定义$G(a,b)$表示:我们将树上从a走到b经过的点都拿出来,设这些点的点权分别为$z_0,z_1... ...

  5. 【CF725G】Messages on a Tree 树链剖分+线段树

    [CF725G]Messages on a Tree 题意:给你一棵n+1个节点的树,0号节点是树根,在编号为1到n的节点上各有一只跳蚤,0号节点是跳蚤国王.现在一些跳蚤要给跳蚤国王发信息.具体的信息 ...

  6. 【SPOJ】QTREE7(Link-Cut Tree)

    [SPOJ]QTREE7(Link-Cut Tree) 题面 洛谷 Vjudge 题解 和QTREE6的本质是一样的:维护同色联通块 那么,QTREE6同理,对于两种颜色分别维护一棵\(LCT\) 每 ...

  7. 【SPOJ】Count On A Tree II(树上莫队)

    [SPOJ]Count On A Tree II(树上莫队) 题面 洛谷 Vjudge 洛谷上有翻译啦 题解 如果不在树上就是一个很裸很裸的莫队 现在在树上,就是一个很裸很裸的树上莫队啦. #incl ...

  8. 【BZOJ2870】最长道路tree 点分治+树状数组

    [BZOJ2870]最长道路tree Description H城很大,有N个路口(从1到N编号),路口之间有N-1边,使得任意两个路口都能互相到达,这些道路的长度我们视作一样.每个路口都有很多车辆来 ...

  9. 【数据挖掘】分类之decision tree(转载)

    [数据挖掘]分类之decision tree. 1. ID3 算法 ID3 算法是一种典型的决策树(decision tree)算法,C4.5, CART都是在其基础上发展而来.决策树的叶子节点表示类 ...

随机推荐

  1. 在vue中运用mt-loadmore 实现上拉加载,下拉刷新

    元旦了,给手残党直接复制的机会,代码如下: 1. :style="{'-webkit-overflow-scrolling': scrollMode}" 最外层div设置,以便兼容 ...

  2. Tools: java安装指南

    参考: https://www.cnblogs.com/smyhvae/p/3788534.htmljava安装 (1)新建->变量名"JAVA_HOME",变量值" ...

  3. jenkins构建结果企业微信提醒

    每当jenkin在构建之后我们想把构建结果SUCCESS/FAILURE或者其他信息通知给其他人,也许有人会说,不是有邮件提醒吗?但是我这里的环境邮件提醒的话所被通知者并不会第一时间去阅读,所以我们用 ...

  4. loj2001[SDOI2017]树点染色

    题意:给你一棵树,一开始每个点上的颜色互不相同.三种操作:op1:x到根的路径上的点都染上一种新的颜色.op2:设一条路径的权值为val(x,y),求x到y路径的val.op3:询问x的子树中最大的到 ...

  5. 24. Java SE 、 Java EE 、JavaME 、 JavaWeb 直接的区别和联系

    这个是在别人博客抄的,并不是本人撰写 Java是一门编程语言.Java分为三大版本,SE即标准版,包含了Java核心类库,主要用来开发桌面应用:EE即企业版,包含SE,又有扩展部分(Servlet,J ...

  6. cut sort uniq wc 一 文本处理工具

    cut cut是一个选取命令,就是将一段数据经过分析,取出我们想要的. 一般来说,选取信息通常是针对"行"来进行分析的,并不是整篇信息分析的. -c : 以字符为单位进行分割. c ...

  7. 线程池 一 ThreadPoolExecutor

    java.util.concurrent public class ThreadPoolExecutor extends AbstractExecutorService ThreadPoolExecu ...

  8. Kafka高级API和低级API

    Kafka消费过程分析 kafka提供了两套consumer API:高级Consumer API和低级API. 1 高级API 1)高级API优点 高级API 写起来简单 不需要去自行去管理offs ...

  9. NX二次开发-UFUN获取工程图详细信息UF_DRAW_ask_drawing_info

    NX9+VS2012 #include <uf.h> #include <uf_draw.h> #include <uf_part.h> UF_initialize ...

  10. NX二次开发-设置对象名称函数UF_OBJ_set_name

    NX9+VS2012 #include <uf.h> #include <uf_modl.h> #include <uf_obj.h> UF_initialize( ...