Dash Speed
来源:互联网 发布:青山知可子女机械人511 编辑:程序博客网 时间:2024/05/18 03:46
题目描述
一棵有n个点的树 每条边有限制li 和ri 只有当询问满足li≤qi≤ri 时才能通过这条边
求对于每个询问 最多可以在一条简单路径上通过多少条边
算法1
对于每个询问从一个点开始DFS 过程中更新ans即可
O(n^2)
算法2
可以把询问和边都按限制从大到小排序
模拟Kruskal求最小生成树 维护每个联通块的大小
询问的答案即为最大的联通块的大小
O(n*log(n))
算法3
树为一条链
询问其实就是求完全包含
把一条边的限制拆成两个 看成在
用线段树维护一个时刻的最大由打了标记的点构成的联通块 它的大小即为询问的答案
这是一个常规的线段树问题
每个线段树的节点维护区间内前后缀以及当前区间的最大联通块即可
O(n*log(n))
算法4
考虑把算法2中的链引申为树
链上一个联通块的最长链就是由左端点到右端点 因此就是联通块的大小
而树的合并时就要分类讨论了
并查集中每个联通块记录左端点
那么显然合并后的联通块的两端点必定在合并前两个联通块的四个端点中
而这四个点有
对于每种情况求两点间距离取最大值即可
O(n*log(n))
算法5
考虑分治
对于分治的一个区间
用算法4的方法合并
然后分治两个子区间
这样是要撤销合并操作的 所以并查集要按秩合并
合并时还要存储被合并的并查集的各种信息 以及当前ans
分治完后全部还原 然后返回上一区间
在预处理时为了方便 在线段树上把边插入对应区间 分治时直接读取即可
还要把询问插入对应的点中 在分治到一个点时回答所有询问
O(n*log(n)^2)
一个小优化 如果当前区间没有任何询问 就不需要向下分治了
我用的是树链剖分求LCA 写起来方便一些
#include<bits/stdc++.h>using namespace std;#define N 70010#define Lc p<<1#define Rc p<<1|1void rd(int &x){ char c;x=0; while (c=getchar(),c<48); do x=(x<<3)+(x<<1)+(c^48); while (c=getchar(),c>=48);}struct edge{ int nxt,t,l,r;}e[N<<1];int tot,head[N];void add_edge(int x,int y,int l,int r){ e[tot]=(edge){head[x],y,l,r}; head[x]=tot++; e[tot]=(edge){head[y],x,l,r}; head[y]=tot++;}struct road{ int x,y,l,r;}E[N];struct query{ int a,id;}Q[N];struct cpy{ int x,y,l,r,siz,len;}cop[N];int dep[N],siz[N],fa[N],son[N],top[N],ans[N],F[N],L[N],R[N],Len[N],res,rec;vector<int>B[N];int n,m;struct Segment_Tree{ vector<int>A[N<<2]; int sum[N<<2]; void add(int l,int r,int p,int x){ if (E[x].l<=l && E[x].r>=r){ A[p].push_back(x); return; } int mid=(l+r)>>1; if (E[x].r<=mid) add(l,mid,Lc,x); else if (E[x].l>mid) add(mid+1,r,Rc,x); else add(l,mid,Lc,x),add(mid+1,r,Rc,x); } void build(int l,int r,int p){ if (l==r){ sum[p]=B[l].size(); return; } int mid=(l+r)>>1; build(l,mid,Lc); build(mid+1,r,Rc); sum[p]=sum[Lc]+sum[Rc]; }}T;void dfs(int x,int f){ dep[x]=dep[f]+1; siz[x]=1; fa[x]=f; int i; for (i=head[x];~i;i=e[i].nxt){ int to=e[i].t; if (to==f) continue; dfs(to,x); siz[x]+=siz[to]; if (siz[to]>siz[son[x]]) son[x]=to; }}void dfs1(int x,int tp){ top[x]=tp; if (son[x]) dfs1(son[x],tp); int i; for (i=head[x];~i;i=e[i].nxt){ int to=e[i].t; if (to==fa[x] || to==son[x]) continue; dfs1(to,to); }}int LCA(int x,int y){ while (top[x]!=top[y]){ if (dep[top[x]]<dep[top[y]]) swap(x,y); x=fa[top[x]]; } return dep[x]<dep[y]?x:y;}int get(int x){return F[x]==x?x:get(F[x]);}int Dis(int x,int y){return dep[x]+dep[y]-dep[LCA(x,y)]*2;}void merge(int x,int y){ int p=get(x),q=get(y); if (p==q) return; if (siz[p]<siz[q]) swap(p,q); cop[++rec]=(cpy){p,q,L[p],R[p],siz[p],Len[p]}; F[q]=p; siz[p]+=siz[q]; int x1=L[p],x2=R[p],x3=L[q],x4=R[q]; if (Len[q]>Len[p]){ Len[p]=Len[q]; L[p]=L[q]; R[p]=R[q]; } int t; t=Dis(x1,x3); if (t>Len[p]){ Len[p]=t; L[p]=x1; R[p]=x3; } t=Dis(x1,x4); if (t>Len[p]){ Len[p]=t; L[p]=x1; R[p]=x4; } t=Dis(x2,x3); if (t>Len[p]){ Len[p]=t; L[p]=x2; R[p]=x3; } t=Dis(x2,x4); if (t>Len[p]){ Len[p]=t; L[p]=x2; R[p]=x4; } res=max(res,Len[p]);}void work(int l,int r,int p){ if (!T.sum[p]) return; int i,tmp=rec,tmp1=res; for (i=0;i<T.A[p].size();i++){ int t=T.A[p][i]; merge(E[t].x,E[t].y); } if (l==r) for (i=0;i<B[l].size();i++) ans[B[l][i]]=res; else{ int mid=(l+r)>>1; work(l,mid,Lc); work(mid+1,r,Rc); } while (rec>tmp){ int x=cop[rec].x,y=cop[rec].y; F[y]=y; L[x]=cop[rec].l; R[x]=cop[rec].r; siz[x]=cop[rec].siz; Len[x]=cop[rec].len; rec--; } res=tmp1;}void solve(){ int i; dfs(1,0); dfs1(1,1); for (i=1;i<n;i++) T.add(1,n,1,i); for (i=1;i<=n;i++) F[i]=L[i]=R[i]=i,siz[i]=1; for (i=1;i<=m;i++) B[Q[i].a].push_back(Q[i].id); T.build(1,n,1); work(1,n,1); for (i=1;i<=m;i++) printf("%d\n",ans[i]);}int main(){ memset(head,-1,sizeof(head)); rd(n),rd(m); int i; for (i=1;i<n;i++){ int x,y,l,r; rd(x),rd(y),rd(l),rd(r); add_edge(x,y,l,r); E[i]=(road){x,y,l,r}; } for (i=1;i<=m;i++) rd(Q[i].a),Q[i].id=i; solve(); return 0;}
Date:2017/10/4
By CalvinJin
- Dash speed
- Dash Speed
- Dash Speed
- Dash Speed
- Dash Speed
- JZOJ4864. Dash Speed
- 【GDOI2017模拟11.5】Dash Speed
- test2 Problem C. Dash Speed (并查集+分治)
- DASH
- Dash
- speed
- bash & dash
- DASH PPT
- dash -> bash
- DASH相关
- Dash第一
- dash激活
- 【Dash】Dash相关领域知识总结
- SpringBoot23-spingboot数据访问-Spring Data REST
- [USACO13NOV]没有找零No Change
- c#读取ini配置文件、将配置数据保存至ini文件
- 聪明的开发者们,中秋不来猜个谜吗?
- C#--Winform-按照班级名称查询学员列表并优化
- Dash Speed
- Firefox 新版采用新引擎,速度是旧版的 2 倍,名字和 Logo 也变了
- [USACO13DEC]假期计划(黄金)Vacation Planning (gold)
- 11章,关联容器
- 2017.10.4离线赛总结
- SPI通讯协议介绍(有见地,学法可取)
- 远程访问VPN Easy VPN --route
- 开启java的进阶之路前言
- 实现OLAP在非税系统的应用的一个方案