题面

题解

\(std\)爆栈了→_→

我们先考虑一个简化的问题,如果只有加边的情况下如何动态维护直径

合并两棵树时,设\(a,b\)为\(A\)的直径的两个端点,\(c,d\)为\(B\)的直径的两个端点,那么新的树的直径一定是\(ab,ac,ad,bc,bd,cd\)中的一个

证明:新树的直径一定是原树的直径或一条经过\((u,v)\)的链(其中\((u,v)\)为新加的边),这条经过\((u,v)\)的链肯定是\(A\)中离\(u\)最远的点到\(u+(u,v)+v\)到\(B\)中离\(v\)最远的点,感性理解一下易知,其中前者必为\(a\)或\(b\),后者必为\(c\)或\(d\)

于是,我们可以对于每一个连通块维护直径的两个端点,每次合并两个连通块时用六个值里的最大值更新答案,顺便用并查集维护即可

然而现在不仅需要加边还需要删边,我们对速度进行分治,设分治区间为\((l,r)\),每一次将所有承受区间完全包含\((l,r)\)的边加入,剩下的继续递归下去

因为我们在回溯的时候需要把递归里的连通块关系给删掉,所以这里需要可持久化并查集,或者简单的说就是并查集的时候只按秩合并,不路径压缩

//minamoto
#include<bits/stdc++.h>
#define R register
#define pi pair<int,int>
#define fi first
#define se second
#define ls (p<<1)
#define rs (p<<1|1)
#define fp(i,a,b) for(R int i=a,I=b+1;i<I;++i)
#define fd(i,a,b) for(R int i=a,I=b-1;i>I;--i)
#define go(u) for(int i=head[u],v=e[i].v;i;i=e[i].nx,v=e[i].v)
#define gg(u) for(vector<eg>::iterator it=pos[u].begin();it!=pos[u].end();++it)
template<class T>inline bool cmax(T&a,const T&b){return a<b?a=b,1:0;}
using namespace std;
char buf[1<<21],*p1=buf,*p2=buf;
inline char getc(){return p1==p2&&(p2=(p1=buf)+fread(buf,1,1<<21,stdin),p1==p2)?EOF:*p1++;}
int read(){
R int res=1,f=1;R char ch;
while((ch=getc())>'9'||ch<'0')(ch=='-')&&(f=-1);
for(res=ch-'0';(ch=getc())>='0'&&ch<='9';res=res*10+ch-'0');
return res*f;
}
char sr[1<<21],z[21];int K=-1,Z=0;
inline void Ot(){fwrite(sr,1,K+1,stdout),K=-1;}
void print(R int x){
if(K>1<<20)Ot();if(x<0)sr[++K]='-',x=-x;
while(z[++Z]=x%10+48,x/=10);
while(sr[++K]=z[Z],--Z);sr[++K]='\n';
}
const int N=1e5+5,M=N<<5;
struct Gr{
struct eg{int v,nx;}e[N<<1];int head[N],tot;
inline void add(R int u,R int v){e[++tot]={v,head[u]},head[u]=tot;}
int dep[N],top[N],fa[N],sz[N],son[N];
void dfs1(int u){
sz[u]=1,dep[u]=dep[fa[u]]+1;
go(u)if(v!=fa[u]){
fa[v]=u,dfs1(v),sz[u]+=sz[v];
if(sz[v]>sz[son[u]])son[u]=v;
}
}
void dfs2(int u,int t){
top[u]=t;if(!son[u])return;
dfs2(son[u],t);
go(u)if(!top[v])dfs2(v,v);
}
int LCA(int u,int v){
while(top[u]!=top[v]){
if(dep[top[u]]<dep[top[v]])swap(u,v);
u=fa[top[u]];
}
return dep[u]<dep[v]?u:v;
}
inline int dis(R int u,R int v){return dep[u]+dep[v]-(dep[LCA(u,v)]<<1);}
}G;
struct node{
int x,y,v;pi p;
node(){}
node(R int X,R int Y,R int V,R pi P):x(X),y(Y),v(V),p(P){}
}st[N];
struct eg{
int u,v;
eg(){}
eg(R int u,R int v):u(u),v(v){}
};
pi li[N];vector<eg>pos[M];
int fa[N],ans[N],dep[N];
int n,m,top;
int find(int x){return fa[x]==x?x:find(fa[x]);}
void ins(int p,int l,int r,int ql,int qr,int u,int v){
if(ql<=l&&qr>=r)return pos[p].push_back(eg(u,v)),void();
int mid=(l+r)>>1;
if(ql<=mid)ins(ls,l,mid,ql,qr,u,v);
if(qr>mid)ins(rs,mid+1,r,ql,qr,u,v);
}
void merge(int u,int v,int &ans){
// printf("%d %d ",u,v);
u=find(u),v=find(v);
int a=li[u].fi,b=li[u].se,c=li[v].fi,d=li[v].se,res=-1;
// printf("%d %d %d %d\n",a,b,c,d);
pi p;
if(cmax(res,G.dis(a,b)))p=pi(a,b);
if(cmax(res,G.dis(a,c)))p=pi(a,c);
if(cmax(res,G.dis(a,d)))p=pi(a,d);
if(cmax(res,G.dis(b,c)))p=pi(b,c);
if(cmax(res,G.dis(b,d)))p=pi(b,d);
if(cmax(res,G.dis(c,d)))p=pi(c,d);
cmax(ans,res);
if(dep[u]<dep[v])swap(u,v);
st[++top]=node(u,v,0,li[u]);
if(dep[u]==dep[v])++dep[u],st[top].v=1;
fa[v]=u,li[u]=p;
// printf("%d\n",res);
}
void del(int cur){
while(top>cur){
dep[st[top].x]-=st[top].v,fa[st[top].y]=st[top].y;
li[st[top].x]=st[top].p,--top;
}
}
void solve(int p,int l,int r,int res){
int now=top;
gg(p)merge(it->u,it->v,res);
if(l==r)ans[l]=res;
else{
int mid=(l+r)>>1;
solve(ls,l,mid,res);
solve(rs,mid+1,r,res);
}
del(now);
}
int x;
int main(){
// freopen("testdata.in","r",stdin);
freopen("speed.in","r",stdin);
freopen("speed.out","w",stdout);
n=read(),m=read();
fp(i,1,n-1){
int u=read(),v=read(),l=read(),r=read();
G.add(u,v),G.add(v,u);
ins(1,1,n,l,r,u,v);
}
G.dfs1(1),G.dfs2(1,1);
fp(i,1,n)fa[i]=i,li[i]=pi(i,i);
solve(1,1,n,0);
while(m--)x=read(),print(ans[x]);
return Ot(),0;
}

Claris’ Contest # 2 Day 2 Problem C. Dash Speed(分治+可持久化并查集+树剖)的更多相关文章

  1. The Preliminary Contest for ICPC Asia Xuzhou 2019 B. so easy (unordered_map+并查集)

    这题单用map过不了,太慢了,所以改用unordered_map,对于前面删除的点,把它的父亲改成,后面一位数的父亲,初始化的时候,map里是零,说明它的父亲就是它本身,最后输出答案的时候,输出每一位 ...

  2. HDU 6326.Problem H. Monster Hunter-贪心(优先队列)+流水线排序+路径压缩、节点合并(并查集) (2018 Multi-University Training Contest 3 1008)

    6326.Problem H. Monster Hunter 题意就是打怪兽,给定一棵 n 个点的树,除 1 外每个点有一只怪兽,打败它需要先消耗 ai点 HP,再恢复 bi点 HP.求从 1 号点出 ...

  3. CodeForces - 688C:NP-Hard Problem (二分图&带权并查集)

    Recently, Pari and Arya did some research about NP-Hard problems and they found the minimum vertex c ...

  4. D. The Door Problem 带权并查集

    http://codeforces.com/contest/776/problem/D 注意到每扇门都有两个东西和它连接着,那么,如果第i扇门的状态是1,也就是已经打开了,那么连接它的两个按钮的状态应 ...

  5. Dash Speed【好题,分治,并查集按秩合并】

    Dash Speed Online Judge:NOIP2016十联测,Claris#2 T3 Label:好题,分治,并查集按秩合并,LCA 题目描述 比特山是比特镇的飙车圣地.在比特山上一共有 n ...

  6. AtCoder Beginner Contest 049 & ARC065 連結 / Connectivity AtCoder - 2159 (并查集)

    Problem Statement There are N cities. There are also K roads and L railways, extending between the c ...

  7. Codeforces Round #423 (Div. 2, rated, based on VK Cup Finals) Problem C (Codeforces 828C) - 链表 - 并查集

    Ivan had string s consisting of small English letters. However, his friend Julia decided to make fun ...

  8. 1326: The contest(并查集+分组背包)

    http://acm.csu.edu.cn/OnlineJudge/problem.php?id=1326 殷犇有很多队员.他们都认为自己是最强的,于是,一场比赛开始了~ 于是安叔主办了一场比赛,比赛 ...

  9. Codeforces 954I Yet Another String Matching Problem(并查集 + FFT)

    题目链接  Educational Codeforces Round 40  Problem I 题意  定义两个长度相等的字符串之间的距离为:   把两个字符串中所有同一种字符变成另外一种,使得两个 ...

随机推荐

  1. Java_JS_01_java调用js

    二.资源帖 1.JAVA执行javascript方法 2.在Java中直接调用js代码 3.Java执行js脚本 4.Java 8 Nashorn 教程 5.Java 脚本引擎

  2. JavaUtil_09_email_使用 commons-email 发送邮件

    二.参考资料 1.[commons]邮件发送工具——commons-email

  3. BEC listen and translation exercise 37

    You're supposed to do that before 10.30 in the morning, but obviously, if it's an emergency, you can ...

  4. Python 爬虫 —— 文件及文件夹操作

    0. 文件名.路径信息.拓展名等 #取文件后缀 >>> os.path.splitext("/root/a.py") ('/root/a', '.py') #取目 ...

  5. InvalidOperationException: out of sync

    C#中不能在集合的迭代中修改集合数据

  6. 搭建DNS服务器-bind

    1. 安装 yum install -y bind-chroot yum install -y bind-utils service named-chroot start    2. 修改配置 增加一 ...

  7. BZOJ1113:[POI2008]PLA

    浅谈栈:https://www.cnblogs.com/AKMer/p/10278222.html 题目传送门:https://lydsy.com/JudgeOnline/problem.php?id ...

  8. Python-Redis的List操作

    Redis列表是简单的字符串列表,一个列表可以包含超过40亿个元素 lpush(name,values):在name对应的list中添加元素,每个新的元素都添加到列表的最左边 rpush(name, ...

  9. asp弹出层

    asp弹出层 <style type="text/css"> html, body { height: %; width: %; } .white_content { ...

  10. day01_虚拟机与主机之间ip配置

       虚拟机1: centos_ node1 虚拟机2:centos_node2 宿主主机虚拟机ip配置: vmnet1 来自为知笔记(Wiz)