【GDOI2017模拟11.5】Dash Speed
来源:互联网 发布:linux卸载svn服务器 编辑:程序博客网 时间:2024/05/20 11:37
Description
给出n个点的一棵树,每条边有一个限制区间[l,r]。
给出m次询问,每次询问给出一个数x,求一条最长的所有边都满足l<=x<=r的路径。
n,m<=7*10^4
Solution
一开始看错数据范围,以为是7*10^5,虚的我。。。
然而没想到每次询问就是相当于保留所有l<=x<=r的边,求森林的直径
考虑分治(据说这也是cdq分治)
首先把每一条边放到所有它完全包含的分治区间中。
然后当我们做到当前区间时,把这个区间中的所有边加入森林中去。
回溯时候再把这些边删掉。
不过因为要兹瓷删边,所以我们的并查集不能路径压缩,只能按秩合并。。。
跑的慢死了。。。
Code
#include <cmath>#include <cstdio>#include <cstring>#include <algorithm>#define fo(i,a,b) for(int i=a;i<=b;i++)#define fd(i,a,b) for(int i=a;i>=b;i--)#define rep(i,a) for(int i=last[a];i;i=next[i])using namespace std;const int N=7*1e4+5;struct note{int a,pa,pb,x,bz;}pr[N*20];int n,m,cnt,tot,ans,x,y,l,r,mx,mi[18],ln[N*2];int d[N],f[N],fir[N],dfn[N*2],g[N*2][18],p[N][2],q[N*20],rank[N],an[N];int t[N*2],next[N*2],last[N],la[N*4],ne[N*20],A[N*20],B[N*20];void add(int x,int y) { t[++cnt]=y;next[cnt]=last[x];last[x]=cnt;}int max(int x,int y) { if (x>y) return x;else return y;}void insert(int v,int l,int r,int x,int y,int a,int b) { if (x<=l&&r<=y) { A[++tot]=a;B[tot]=b;mx=max(mx,v); ne[tot]=la[v];la[v]=tot; return; } int m=(l+r)/2; if (x<=m) insert(v*2,l,m,x,y,a,b); if (y>m) insert(v*2+1,m+1,r,x,y,a,b);}void dfs(int x,int y) { d[x]=d[y]+1;dfn[++tot]=x;fir[x]=tot; rep(i,x) if (t[i]!=y) dfs(t[i],x),dfn[++tot]=x;}int get(int x) { return f[x]?get(f[x]):x;}int lca(int x,int y) { x=fir[x];y=fir[y]; if (x>y) swap(x,y); int z=ln[y-x+1]; if (d[dfn[g[x][z]]]<d[dfn[g[y-mi[z]+1][z]]]) return dfn[g[x][z]]; else return dfn[g[y-mi[z]+1][z]];}int len(int x,int y) { int z=lca(x,y); return d[x]+d[y]-2*d[z];}void merge(int x,int &ans) { int ax=get(A[x]),ay=get(B[x]);tot++; int now[2],cnt;now[0]=p[ax][0];now[1]=p[ax][1];cnt=len(now[0],now[1]); int dist=len(p[ay][0],p[ay][1]); if (dist>cnt) cnt=dist,now[0]=p[ay][0],now[1]=p[ay][1]; fo(j,0,1) fo(k,0,1) { dist=len(p[ax][j],p[ay][k]); if (dist>cnt) cnt=dist,now[0]=p[ax][j],now[1]=p[ay][k]; } if (rank[ay]<rank[ax]) { pr[x].x=ay;pr[x].a=ax; pr[x].pa=p[ax][0];pr[x].pb=p[ax][1]; p[ax][0]=now[0];p[ax][1]=now[1]; f[ay]=ax; } else { pr[x].x=ax;pr[x].a=ay; pr[x].pa=p[ay][0];pr[x].pb=p[ay][1]; p[ay][0]=now[0];p[ay][1]=now[1]; f[ax]=ay; if (rank[ax]==rank[ay]) rank[ay]++,pr[x].bz=1; } ans=max(ans,len(now[0],now[1]));}void del(int x) { for(int i=la[x];i;i=ne[i]) q[++q[0]]=i; while (q[0]) { p[pr[q[q[0]]].a][0]=pr[q[q[0]]].pa; p[pr[q[q[0]]].a][1]=pr[q[q[0]]].pb; f[pr[q[q[0]]].x]=0;rank[pr[q[q[0]]].a]-=pr[q[q[0]]].bz; q[0]--; }}void work(int v,int l,int r,int ans) { for(int i=la[v];i;i=ne[i]) merge(i,ans); if (l==r) { an[l]=ans; del(v); return; } int m=(l+r)/2; work(v*2,l,m,ans); work(v*2+1,m+1,r,ans); del(v);}int main() { freopen("speed.in","r",stdin); freopen("speed.out","w",stdout); scanf("%d%d",&n,&m); fo(i,1,n-1) { scanf("%d%d%d%d",&x,&y,&l,&r); add(x,y);add(y,x); insert(1,1,n,l,r,x,y); } tot=0;dfs(1,0);mi[0]=1; fo(i,1,tot) g[i][0]=i,ln[i]=log(i)/log(2);fo(i,1,17) mi[i]=mi[i-1]*2; fo(j,1,17) fo(i,1,tot-mi[j]+1) if (d[dfn[g[i][j-1]]]<d[dfn[g[i+mi[j-1]][j-1]]]) g[i][j]=g[i][j-1]; else g[i][j]=g[i+mi[j-1]][j-1]; fo(i,1,n) p[i][0]=p[i][1]=i; work(1,1,n,0); fo(i,1,m) scanf("%d",&x),printf("%d\n",an[x]);}
0 0
- 【GDOI2017模拟11.5】Dash Speed
- Dash speed
- Dash Speed
- Dash Speed
- Dash Speed
- Dash Speed
- 【GDOI2017模拟11.5】Market
- 【GDOI2017模拟11.5】Market
- GDOI2017模拟11.5 总结
- JZOJ4864. Dash Speed
- 4863. 【GDOI2017模拟11.5】Market
- JZOJ 4863. 【GDOI2017模拟11.5】Market
- JZOJ 4863 【GDOI2017模拟11.5】Market
- 【GDOI2017模拟7.17】两棵树
- 【GDOI2017模拟8.11】总结
- 【GDOI2017模拟8.12】躲藏
- 【GDOI2017模拟8.12】字符串
- 【GDOI2017模拟8.12】新车
- https详细介绍
- UIBezierPath、CADisplayLink实现波浪动画
- 简单了解Http协议
- nginx centos6 minimal 下安装
- me and my broken heart(后缀表达式)
- 【GDOI2017模拟11.5】Dash Speed
- MyISAM和InnoDB的区别
- iOS 几种定时方式
- nodejs 安装配置和调试
- iOS - Xcode8编译卡顿的解决方法
- 【ZJOI2009】狼和羊的故事
- 基于attention的video描述
- python学习笔记2
- 数据库结构的设计