题目大意:给你一颗n个节点的树,最初点集S为空。

有m次操作:往当前点集S中加入/删除一个点,询问点x至集合S中任意点的最小距离,回到第t次修改点集的操作后的状态。

数据范围:$n,m≤10^5$

我们先无视这个可持久化的要求,考虑下不可持久化怎么做。

显然考虑动态树分治。

令点v为当前分治中心,u为v在点分树上的父亲,

每个点开一个数组D,D[x]表示以v为根的点分树中,与v距离为不大于x的点的标记点数量。

我们借助这个数组,可以方便地求出从v走最少多少步可以走到一个标记点。

首先考虑查询操作,我们可以直接在点分树上从x开始往上跳,设当前跳到了点y,我们需要在这个点的D数组中找到一个最大的k,满足D[k]=0。 那么我们不难发现此时找到的距离点x最近的点距离为$k+dis(x,y)+1$。

至于为什么不需要像正常动态点分治那样容斥相减,那是因为此处我们只需要找到一个距离最近的即可,不去重也不会对答案有影响(这是我后来才发现的,场上写了相减的。。。。)

至于修改操作,我们直接在点分树上从x开始网上跳,设当前跳到了y,我们修改下$D[dis(x,y)]$后面的数据即可。

我们为了优化复杂度显然不可以暴力修改/查询D数组,在这里我们用线段树维护D数组即可。

然而此题中还要求要可持久化,把线段树换成可持久化线段树就可以了。

时间复杂度:$O(n\log^2\ n)$

代码后来优化了一波,不算太长。

 #include<bits/stdc++.h>
#define M 100005
#define N 20000005
using namespace std; struct edge{int u,next;}e[M*]={}; int head[M]={},Use=;
void add(int x,int y){Use++;e[Use].u=y;e[Use].next=head[x];head[x]=Use;}
int T=,newT=,n,pointcnt[M]={}; int f[M][]={},dep[M]={};
void dfs(int x,int fa){
f[x][]=fa; dep[x]=dep[fa]+;
for(int i=;i<;i++) f[x][i]=f[f[x][i-]][i-];
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa) dfs(e[i].u,x);
}
int getlca(int x,int y){
if(dep[x]<dep[y]) swap(x,y); int cha=dep[x]-dep[y];
for(int i=;~i;i--) if((<<i)&cha) x=f[x][i];
for(int i=;~i;i--) if(f[x][i]!=f[y][i]) x=f[x][i],y=f[y][i];
if(x==y) return x; return f[x][];
}
int getdis(int x,int y){return dep[x]+dep[y]-*dep[getlca(x,y)];} int fa[M]={},vis[M]={},siz[M]={},minn=,minid=;
void dfssiz(int x,int fa){
siz[x]=;
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa&&vis[e[i].u]==) dfssiz(e[i].u,x),siz[x]+=siz[e[i].u];
}
void dfsmax(int x,int fa,int fsiz){
int maxn=fsiz-siz[x];
for(int i=head[x];i;i=e[i].next) if(e[i].u!=fa&&vis[e[i].u]==) dfsmax(e[i].u,x,fsiz),maxn=max(maxn,siz[e[i].u]);
if(maxn<minn) minn=maxn,minid=x;
}
int makeroot(int x){dfssiz(x,); minn=M; dfsmax(x,,siz[x]); return minid;}
void solve(int x,int Fa){
x=makeroot(x); vis[x]=; fa[x]=Fa;
for(int i=head[x];i;i=e[i].next) if(vis[e[i].u]==) solve(e[i].u,x);
} int lc[N]={},rc[N]={},sum[N]={},use=;
void updata(int &x,int l,int r,int k,int val){
use++; lc[use]=lc[x]; rc[use]=rc[x]; sum[use]=sum[x]+val;
x=use; int mid=(l+r)>>; if(l==r) return;
if(k<=mid) updata(lc[x],l,mid,k,val); else updata(rc[x],mid+,r,k,val);
}
int query(int x,int l,int r){
if(sum[x]==) return r;
if(l==r) return -; int mid=(l+r)>>;
int res=query(lc[x],l,mid);
if(res!=mid) return res;
int res2=query(rc[x],mid+,r);
if(res2!=-) return res2; return res;
} struct hh{
int rt; hh(int RT=){rt=RT;}
int query(int x,int l,int r,int k){
if(l==r) return sum[x]; int mid=(l+r)>>;
if(k<=mid) return query(lc[x],l,mid,k);
return query(rc[x],mid+,r,k);
}
int set(int &x,int l,int r,int k,int val){
use++; lc[use]=lc[x]; rc[use]=rc[x]; x=use;
if(l==r) return sum[x]=val;
int mid=(l+r)>>;
if(k<=mid) set(lc[x],l,mid,k,val);
else set(rc[x],mid+,r,k,val);
}
int Query(int id){return query(rt,,n,id);}
int Set(int id,int val){return set(rt,,n,id,val);}
}a[M],on[M]; void Updata(int x,int id,int val){
int rt=a[newT].Query(x);
updata(rt,,n,getdis(x,id),val);
a[newT].Set(x,rt);
if(fa[x]) Updata(fa[x],id,val);
}
int Query(int x,int y){
int res=query(a[T].Query(x),,n)+getdis(x,y);
if(fa[x]) res=min(res,Query(fa[x],y));
return res;
} int main(){
scanf("%d",&n);
for(int i=,x,y;i<n;i++) scanf("%d%d",&x,&y),add(x,y),add(y,x);
dfs(,);
solve(,);
int m,ans=; scanf("%d",&m);
while(m--){
int op,x; scanf("%d%d",&op,&x); x^=ans;
if(op==){T=x; continue;}
if(op==){
newT++; a[newT]=a[T]; on[newT]=on[T];
int sel=on[T].Query(x);
if(sel==){
pointcnt[newT]=pointcnt[T]+;
on[newT].Set(x,);
}else{
pointcnt[newT]=pointcnt[T]-;
on[newT].Set(x,);
}
Updata(x,x,sel==?:-);
T=newT;
}else{
if(pointcnt[T]==) {printf("%d\n",ans=1e9); continue;}
printf("%d\n",ans=Query(x,x)+);
}
}
}

【xsy2818】 最近点 动态树分治+可持久化线段树的更多相关文章

  1. 主席树(可持久化线段树) 静态第k大

    可持久化数据结构介绍 可持久化数据结构是保存数据结构修改的每一个历史版本,新版本与旧版本相比,修改了某个区域,但是大多数的区域是没有改变的, 所以可以将新版本相对于旧版本未修改的区域指向旧版本的该区域 ...

  2. [HNOI2016]树(可持久化线段树+树上倍增)

    [HNOI2016]树(可持久化线段树+树上倍增) 题面 给出一棵n个点的模板树和大树,根为1,初始的时候大树和模板树相同.接下来操作m次,每次从模板树里取出一棵子树,把它作为新树里节点y的儿子.操作 ...

  3. hdu2665 主席树(可持久化线段树)

    题意:给定一个数组,每次查询第l到r区间的第k大值 解法嘛,当然是主席树,主席树即可持久化线段树,什么叫可持久化呢,就是指能够访问历史版本的数据结构,那么对于某些只能离线处理的题目强制在线之后 ,可以 ...

  4. cdqz2017-test10-rehearsal(CDQ分治&可持久化线段树&单调栈)

    题意: 给出n个三元组 e[i]=(si,ti,wi) 第i个三元组的价值为 Σ w[j] ,j 满足以下4个条件: 1.j<i 2.tj<ti 3.sj<si 4.不存在j< ...

  5. bzoj 4137 [FJOI2015]火星商店问题——线段树分治+可持久化01trie树

    题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4137 关于可持久化01trie树:https://www.cnblogs.com/LadyL ...

  6. [FJOI2015]火星商店问题(线段树分治,可持久化,Trie树)

    [FJOI2015]火星商店问题 前天考了到线段树分治模板题,全场都切了,就我不会QAQ 于是切题无数的Tyher巨巨就告诉我:"你可以去看看火星商店问题,看了你就会了." 第一道 ...

  7. 线段树分治总结(线段树分治,线段树,并查集,树的dfn序,二分图染色)

    闲话 stO猫锟学长,满脑子神仙DS 网上有不少Dalao把线段树分治也归入CDQ分治? 还是听听YCB巨佬的介绍: 狭义:只计算左边对右边的贡献. 广义:只计算外部对内部的贡献. 看来可以理解为广义 ...

  8. BZOJ 4771 七彩树(可持久化线段树合并)

    题意 https://www.lydsy.com/JudgeOnline/problem.php?id=4771 思路 和 HDU 3333 其实有点像,不过是把序列的问题放在了树上,多维护一个深度即 ...

  9. 主席树(可持久化线段树)静态区间第K小

    传送门主席树 #include <bits/stdc++.h> #define int long long using namespace std; const int maxn=2e5+ ...

随机推荐

  1. 2018.12.22 bzoj3473: 字符串(后缀自动机+启发式合并)

    传送门 调代码调的我怀疑人生. 启发式合并用迭代写怎么都跑不过(雾 换成了dfsdfsdfs版本的终于过了233. 题意简述:求给出nnn个字串,对于每个给定的字串求出其有多少个字串在至少kkk个剩下 ...

  2. 百度地图经纬度和地址互转(Java代码)

    这是基于springmvc+mybatis 的一个controller.如果不是这个框架,可以把方法实体抽到自己写的一个类中,然后再测试 package com.uwitec.controller.s ...

  3. 安卓 build/core/Makefile 以及main.mk

    android make 系统总共分为四层 arch board device product 在各个字android.mk文件中引用的定义都存放在./build/core/下!比如android.m ...

  4. Spring 整合 RocketMQ

    1. 引入jar包 <!-- RocketMQ --> <dependency> <groupId>com.alibaba.rocketmq</groupId ...

  5. 1098 Insertion or Heap Sort

    1098 Insertion or Heap Sort (25 分) According to Wikipedia: Insertion sort iterates, consuming one in ...

  6. hdu 5090 数列贪心加成1~n

    http://acm.hdu.edu.cn/showproblem.php?pid=5090 给一段长度为n数列,问能否给任意个数加上k的倍数,使得加完之后恰好只有1~n 贪心,先排序,依次加出1~n ...

  7. bootstrap datetimepicker

    一.datepicker 早期的 二.datetimepicker 适用于bootstrap2,3兼容性不太好 三.在github上找了个不错的:https://github.com/Eonasdan ...

  8. SRM479

    250pt: 题意:有一排一共44,777,777个人,每个人需要咖啡或者茶,队伍的头部有一台饮料机,有一个空姐负责给所有人送饮料,她一开始在也头部.空姐拿一个水壶,一开始是空的,可以在饮料机的地方加 ...

  9. 2015-2016-1 学期《软件工程》学生名单-- PS:教材使用《构建之法》第二版 --邹欣著

    1208053044 王威 男 1313023001 饶阳梅 女 1313023002 应蕾蕾 女 1313023004 袁立萍 女 1313023005 黎洋阳 女 1313023006 蒋欣 女 ...

  10. Java 学习的几个基础实验(Learn by doing)

    0 引子 不少情况下,学生连开发环境都搭建不好,有了实验楼,这个问题基本就解决了. 实验楼是国内首家IT在线实训平台,拥有最丰富的计算机在线实验课,而且全部免费.创业团队对师生的服务非常贴心细致. 1 ...