Dash Speed
题目大意:
比特山是比特镇的飙车圣地。在比特山上一共有n 个广场,编号依次为1 到n,这些广场之间通过n - 1 条双向车道直接或间接地连接在一起,形成了一棵树的结构。
因为每条车道的修建时间以及建筑材料都不尽相同,所以可以用两个数字li; ri 量化地表示一条车道的承受区间,只有当汽车以不小于li 且不大于ri 的速度经过这条车道时,才不会对路面造成伤害。
Byteasar 最近新买了一辆跑车,他想在比特山飙一次车。Byteasar 计划选择两个不同的点S; T,然后在它们树上的最短路径上行驶,且不对上面任意一条车道造成伤害。
Byteasar 不喜欢改变速度,所以他会告诉你他的车速。为了挑选出最合适的车速,Byteasar 一共会向你询问m 次。请帮助他找到一条合法的道路,使得路径上经过的车道数尽可能多。
数据范围n,m<=70000.
题解:
(蒟蒻眼中)比较神的树上分治。做法分治[ l , r ] :(丑图奉上)

其中每一个矩形代表分治区间,圆代表提取答案的地方。
每当访问到矩形/圆时,将对应区间加的边更新并查集,然后不断用新集的直径更新当前答案。
(ps.当两棵树合并时,新树的直径一定在旧树的端点中产生。这里需要6次特判。)
每当返回时,将原来的更新取消。可以先记录栈的tl,然后将栈还原。
细节比较多,详细见代码:
upd:由于之前代码太丑被和谐,附上新代码:
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N = ;
template<typename T>
inline void read(T&x)
{
T f = ,c = ;char ch=getchar();
while(ch<''||ch>''){if(ch=='-')f=-;ch=getchar();}
while(ch>=''&&ch<=''){c=c*+ch-'';ch=getchar();}
x = f*c;
}
int n,m,hed[N],cnt,dep[N],siz[N],fa[N],son[N],tp[N];
struct EG
{
int to,nxt;
}e[N<<];
void ae(int f,int t)
{
e[++cnt].to = t;
e[cnt].nxt = hed[f];
hed[f] = cnt;
}
void dfs1(int u,int f)
{
fa[u]=f,dep[u]=dep[f]+,siz[u]=;
for(int j=hed[u],to;j;j=e[j].nxt)
if((to=e[j].to)!=f)
{
dfs1(to,u),siz[u]+=siz[to];
if(siz[son[u]]<siz[to])son[u]=to;
}
}
void dfs2(int u,int Top)
{
tp[u] = Top;
if(!son[u])return ;
dfs2(son[u],Top);
for(int j=hed[u],to;j;j=e[j].nxt)if((to=e[j].to)!=fa[u]&&to!=son[u])
dfs2(to,to);
}
int get_lca(int x,int y)
{
while(tp[x]!=tp[y])
{
if(dep[tp[x]]<dep[tp[y]])swap(x,y);
x = fa[tp[x]];
}
return dep[x]<dep[y]?x:y;
}
int get_dis(int x,int y){return dep[x]+dep[y]-*dep[get_lca(x,y)];}
struct Tree
{
int a,b,w;
Tree(){}
Tree(int a,int b,int w):a(a),b(b),w(w){}
Tree operator + (const Tree&x)const
{
Tree ret = Tree(a,b,w);int tmp;
if(ret.w<x.w)ret=x;
tmp=get_dis(a,x.a);if(ret.w<tmp)ret=Tree(a,x.a,tmp);
tmp=get_dis(a,x.b);if(ret.w<tmp)ret=Tree(a,x.b,tmp);
tmp=get_dis(b,x.a);if(ret.w<tmp)ret=Tree(b,x.a,tmp);
tmp=get_dis(b,x.b);if(ret.w<tmp)ret=Tree(b,x.b,tmp);
return ret;
}
};
int ans[N];
struct segtree
{
struct point
{
Tree s;
int ff,siz;
}p[N];
struct node
{
int u;point p0;
node(){}
node(int u,point p0):u(u),p0(p0){}
}sta[N<<];
int hd[N<<],ct,tl;
struct edge
{
int u,v,nxt;
}E[N<<];
void ae(int f,int u,int v)
{
E[++ct].u = u;
E[ct].v = v;
E[ct].nxt = hd[f];
hd[f] = ct;
}
void insert(int l,int r,int u,int ql,int qr,int&lp,int&rp)
{
if(l==ql&&r==qr){ae(u,lp,rp);return ;}
int mid = (l+r)>>;
if(qr<=mid)insert(l,mid,u<<,ql,qr,lp,rp);
else if(ql>mid)insert(mid+,r,u<<|,ql,qr,lp,rp);
else insert(l,mid,u<<,ql,mid,lp,rp),insert(mid+,r,u<<|,mid+,qr,lp,rp);
}
int findff(int u){return u==p[u].ff?u:findff(p[u].ff);}
void merge(int u,int v,int&now)
{
u = findff(u),v = findff(v);
if(u==v)return ;
if(p[u].siz>p[v].siz)swap(u,v);
sta[++tl]=node(u,p[u]),sta[++tl]=node(v,p[v]);
p[v].s=p[v].s+p[u].s,p[u].ff=v;
if(p[u].siz==p[v].siz)p[v].siz++;
now = max(now,p[v].s.w);
}
void rep(int las)
{
while(tl!=las)p[sta[tl].u]=sta[tl].p0,tl--;
}
void sol(int l,int r,int u,int now)
{
int tim = tl;
for(int j=hd[u];j;j=E[j].nxt)
merge(E[j].u,E[j].v,now);
if(l==r){ans[l]=now;rep(tim);return ;}
int mid = (l+r)>>;
sol(l,mid,u<<,now);sol(mid+,r,u<<|,now);
rep(tim);
}
}tr;
int main()
{
// freopen("tt.in","r",stdin);
read(n),read(m);
for(int u,v,l,r,i=;i<n;i++)
{
read(u),read(v),read(l),read(r);
ae(u,v),ae(v,u);tr.insert(,n,,l,r,u,v);
}
dfs1(,),dfs2(,);
for(int i=;i<=n;i++)
tr.p[i].ff=i,tr.p[i].siz=,tr.p[i].s=Tree(i,i,);
tr.sol(,n,,);
for(int i=,x;i<=m;i++)
read(x),printf("%d\n",ans[x]);
return ;
}
Dash Speed的更多相关文章
- Dash Speed【好题,分治,并查集按秩合并】
Dash Speed Online Judge:NOIP2016十联测,Claris#2 T3 Label:好题,分治,并查集按秩合并,LCA 题目描述 比特山是比特镇的飙车圣地.在比特山上一共有 n ...
- csp-s模拟测试58「Divisors」·「Market」·「Dash Speed」
A. Divisors 大概平均下来每个数也就几千约数吧....,直接筛 B. Market 可以把时间离线下来, 考试没有想到将询问离线,用数组存算了算只能过200的点,拿了70 事实上背包后直 ...
- LYDSY模拟赛day2 Dash Speed
/* 弃坑 */ #include<cstdio> #include<algorithm> using namespace std; ,M=N*; ],nxt[N<< ...
- Claris’ Contest # 2 Day 2 Problem C. Dash Speed(分治+可持久化并查集+树剖)
题面 题解 \(std\)爆栈了→_→ 我们先考虑一个简化的问题,如果只有加边的情况下如何动态维护直径 合并两棵树时,设\(a,b\)为\(A\)的直径的两个端点,\(c,d\)为\(B\)的直径的两 ...
- [CSP-S模拟测试]:Dash Speed(线段树+并查集+LCA)
题目描述 比特山是比特镇的飙车圣地.在比特山上一共有$n$个广场,编号依次为$1$到$n$,这些广场之间通过$n−1$条双向车道直接或间接地连接在一起,形成了一棵树的结构. 因为每条车道的修建时间以及 ...
- HZOJ Dash Speed
测试点1-2:暴力. 测试点3-4:可以将边按r从大到小排序不断加入,然后用并茶几维护深度.好像也可以用猫树做. 好吧其他的部分分并没有看懂. 正解: 线段树分治,求出每个速度的答案. 对于速度区间$ ...
- 联赛模拟测试8 Dash Speed 线段树分治
题目描述 分析 对于测试点\(1\).\(2\),直接搜索即可 对于测试点\(3 \sim 6\),树退化成一条链,我们可以将其看成序列上的染色问题,用线段树维护颜色相同的最长序列 对于测试点\(7\ ...
- 【线段树分治】Dash Speed
代码的美妙 #include <bits/stdc++.h> %:pragma GCC optimize(3) using namespace std; const int maxn=7e ...
- noip2016十连测round2
A: Divisors 题意:给定 m 个不同的正整数 a 1 ,a 2 ,...,a m ,请对 0 到 m 每一个 k 计算,在区间 [1,n] 里有多少正整数 是 a 中恰好 k 个数的约数. ...
随机推荐
- 关于final修饰符
一:修饰成员变量 关于被final修饰的成员属性(常量)初始化赋值问题分为以下两种情况: 1.被static修饰符修饰:可以通过两种途径进行初始化赋值 ① 在常量被定义时进行初始化赋值 ② 在静态代码 ...
- Ubuntu 环境变量及 ADB 配置 (转载)
转自:http://blog.csdn.net/ithomer/article/details/7307449 同Windows一样,Ubuntu Linux系统包含两类环境变量:系统环境变量和用户环 ...
- bzoj 1602: [Usaco2008 Oct]牧场行走【瞎搞】
本来想爆手速写个树剖,然而快下课了就手残写了了个n方的短小-- 暴力把查询的两个点中深的一个跳上来,加上边权,然后一起跳加边权就行了 #include<iostream> #include ...
- Luogu P1137 旅行计划 【拓扑排序+Dp】By cellur925
题目传送门 由于满足游览先后顺序从西到东的性质,我们很自然的想到用拓扑排序处理出一个合理的游览顺序. 然鹅,之后呢? 事实上,拓扑排序常与Dp相结合,解决后效性.我们就可以在每次拓扑入队的时候更新答案 ...
- POJ 2833 The Average(优先队列)
原题目网址:http://poj.org/problem?id=2833 本题中文翻译: 描述 在演讲比赛中,当选手完成演讲时,评委将对他的演出进行评分. 工作人员删除最高成绩和最低成绩,并计算其余成 ...
- Python圈中的符号计算库-Sympy(转载)
<本文来自公众号“大邓带你玩python”,转载> import math math.sqrt(8) 2.8284271247461903 我们看看Python中结果 math.sqrt( ...
- [CTSC2000]丘比特的烦恼
Description 随着社会的不断发展,人与人之间的感情越来越功利化.最近,爱神丘比特发现,爱情也已不再是完全纯洁的了.这使得丘比特很是苦恼,他越来越难找到合适的男女,并向他们射去丘比特之箭.于是 ...
- 图论/暴力 Codeforces Beta Round #94 (Div. 2 Only) B. Students and Shoelaces
题目传送门 /* 图论/暴力:这是个连通的问题,每一次把所有度数为1的砍掉,把连接的点再砍掉,总之很神奇,不懂:) */ #include <cstdio> #include <cs ...
- iOS生成PDF的关键代码-备忘
//此方法只是把当前页面的内容生成PDF并保存在沙盒中. //还需要做:把当前面没有显示的内容以分页的形式生成PDF,并把PDF读取并显示出来 //关于显示可以参考:念茜的博客 iOS开发笔记——PD ...
- windows下Python的安装,以及IDLE的使用
一.Python的下载安装 (1)python的windows安装包可以从https://www.python.org 网址中下载,可以下载3.4版本的或者2.7版本的.(2)下载后直接运行即可.然后 ...