HZOJ Dash Speed
测试点1~2:暴力。
测试点3~4:可以将边按r从大到小排序不断加入,然后用并茶几维护深度。好像也可以用猫树做。
好吧其他的部分分并没有看懂。
正解:
线段树分治,求出每个速度的答案。
对于速度区间$[L,R]$,将完全包含这个区间的边加入,对于其余的边,按照和mid的关系分到左右儿子,这里的一条边有可能同时分到两个儿子所以直接塞vector就行了。
那么到达叶子区间时,满足条件的树的结构已经出来了,答案就是这些联通块的直径。
那么大体思路已经清晰了,如何动态维护树的结构呢?lct!!!并查集即可,维护联通块直径的两个端点,合并时分6中情况讨论即可,注意由于递归完左儿子后还要处理右儿子,所以左儿子中连的边都要清掉,于是并查集不能路径压缩,按秩合并即可(然而我故意把size大的合并到size小的还是A掉了)。
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#define re register
#define co const
#define rec re co
#define LL long long
using namespace std;
struct edge
{
int u,v,nxt,l,r;
#define u(x) ed[x].u
#define v(x) ed[x].v
#define l(x) ed[x].l
#define r(x) ed[x].r
#define n(x) ed[x].nxt
friend bool operator < (edge a,edge b)
{return a.r>b.r;}
}ed[];
int first[],num_e=;
#define f(x) first[x]
int n,m;
int f[][],dep[],size[];
int ttop[],son[],dfn[],id[],cnt;
void dfs1(int x)
{
size[x]=;
for(int i=f(x);i;i=n(i))
if(v(i)!=f[x][])
{
f[v(i)][]=x;dep[v(i)]=dep[x]+;
dfs1(v(i));size[x]+=size[v(i)];
if(size[v(i)]>size[son[x]])son[x]=v(i);
}
}
void dfs2(int x,int t)
{
ttop[x]=t;dfn[x]=++cnt;id[cnt]=x;
if(son[x])dfs2(son[x],t);
for(int i=f(x);i;i=n(i))
if(v(i)!=f[x][]&&v(i)!=son[x])
dfs2(v(i),v(i));
}
inline int LCA(int x,int y)
{
while(ttop[x]!=ttop[y])
{
if(dep[ttop[x]]>dep[ttop[y]])swap(x,y);
y=f[ttop[y]][];
}
if(dep[x]>dep[y])swap(x,y);
return x;
}
#define st sta[top]
#define st2 sta2[top2]
#define st3 sta3[top3]
struct node{int id,pu,pv;}sta[];int top;
struct node2{int id,of;}sta2[];int top2;
struct node3{int id,ad;}sta3[];int top3;
vector<int> in[];
int fa[],u[],v[],al[],siz[];
int get(re int x){return fa[x]==x?x:get(fa[x]);}
LL lenth(re int u,re int v){return dep[u]+dep[v]-dep[LCA(u,v)]*;}
void solve(re int l,re int r,rec int x,re int res)
{
int mid=(l+r)>>,tem=top,tem2=top2,tres=res,tem3=top3;
for(int i=;i<in[x].size();i++)
if(l(in[x][i])<=l&&r(in[x][i])>=r)
{ int f1=get(u(in[x][i])),f2=get(v(in[x][i]));if(f1==f2)continue;
int gl;
if(siz[f1]>siz[f2])
{
fa[f1]=f2;gl=f2;siz[f2]+=siz[f1];
sta[++top]=(node){f2,u[f2],v[f2]};
sta2[++top2]=(node2){f1,f1};
sta3[++top3]=(node3){f2,siz[f1]};
}
else
{
fa[f2]=f1;gl=f1;siz[f1]+=siz[f2];
sta[++top]=(node){f1,u[f1],v[f1]};
sta2[++top2]=(node2){f2,f2};
sta3[++top3]=(node3){f1,siz[f2]};
}
int t1=u[f1],t2=u[f2],t3=v[f1],t4=v[f2];
int max1=lenth(t1,t2),
max2=lenth(t1,t3),
max3=lenth(t1,t4),
max4=lenth(t2,t3),
max5=lenth(t2,t4),
max6=lenth(t3,t4);
int maxn=max(max1,max2);maxn=max(maxn,max3);
maxn=max(maxn,max4);maxn=max(maxn,max5);maxn=max(maxn,max6);
if(maxn==max1)u[gl]=t1,v[gl]=t2;
else if(maxn==max2)u[gl]=t1,v[gl]=t3;
else if(maxn==max3)u[gl]=t1,v[gl]=t4;
else if(maxn==max4)u[gl]=t2,v[gl]=t3;
else if(maxn==max5)u[gl]=t2,v[gl]=t4;
else if(maxn==max6)u[gl]=t3,v[gl]=t4;
res=max(res,maxn);
}
else
{
if(l(in[x][i])<=mid)in[x*].push_back(in[x][i]);
if(r(in[x][i])> mid)in[x*+].push_back(in[x][i]);
}
if(l==r)
{
al[l]=res;
while(top>tem)u[st.id]=st.pu,v[st.id]=st.pv,top--;
while(top2>tem2)fa[st2.id]=st2.of,top2--;
while(top3>tem3)siz[st3.id]-=st3.ad,top3--;
res=tres;
return;
}
solve(l,mid,x*,res);solve(mid+,r,x*+,res);
while(top>tem)u[st.id]=st.pu,v[st.id]=st.pv,top--;
while(top2>tem2)fa[st2.id]=st2.of,top2--;
while(top3>tem3)siz[st3.id]-=st3.ad,top3--;
res=tres;
}
inline int read();
inline void add(rec int u,rec int v,rec int l,rec int r);
signed main()
{
// freopen("speed1.in","r",stdin);
// freopen("out.out","w",stdout); n=read(),m=read();
int tu,tv,tl,tr;
for(re int i=;i<n;i++)
{
tu=read(),tv=read(),tl=read(),tr=read();
add(tu,tv,tl,tr);add(tv,tu,tl,tr);
}
dfs1(),dfs2(,);
for(re int i=;i<=;i++)
for(re int j=;j<=n;j++)
f[j][i]=f[f[j][i-]][i-];
for(re int i=;i<=n;i++)fa[i]=u[i]=v[i]=i,siz[i]=;
for(re int i=;i<=num_e;i+=)in[].push_back(i);
solve(,n,,);
int q;
for(re int i=;i<=m;i++)
{
q=read();
printf("%d\n",al[q]);
}
}
inline int read()
{
int s=,f=;char a=getchar();
while(a<''||a>''){if(a=='-')f=-;a=getchar();}
while(a>=''&&a<=''){s=s*+a-'';a=getchar();}
return s*f;
}
inline void add(rec int u,rec int v,rec int l,rec int r)
{
++num_e;
u(num_e)=u;
v(num_e)=v;
l(num_e)=l;
r(num_e)=r;
n(num_e)=f(u);
f(u)=num_e;
}
HZOJ 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\)的直径的两 ...
- Dash Speed
题目大意: 比特山是比特镇的飙车圣地.在比特山上一共有n 个广场,编号依次为1 到n,这些广场之间通过n - 1 条双向车道直接或间接地连接在一起,形成了一棵树的结构.因为每条车道的修建时间以及建筑材 ...
- [CSP-S模拟测试]:Dash Speed(线段树+并查集+LCA)
题目描述 比特山是比特镇的飙车圣地.在比特山上一共有$n$个广场,编号依次为$1$到$n$,这些广场之间通过$n−1$条双向车道直接或间接地连接在一起,形成了一棵树的结构. 因为每条车道的修建时间以及 ...
- 联赛模拟测试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 个数的约数. ...
随机推荐
- CF 578B "Or" Game
传送门 解题思路 题意大概是给你一个数列,可以进行k次操作,每次操作可以选择一个数乘x,问操作后的或的最大值.根据位运算,位数越高答案越优,所以贪心的使这k次操作全都放到一个数上,这样的结果肯定较优. ...
- Vijos 学姐的逛街计划
传送门 题解传送门 线性规划,最小费用最大流. 神奇的操作. //Achen #include<algorithm> #include<iostream> #include&l ...
- Delphi 设计模式:《HeadFirst设计模式》Delphi7代码---状态模式[转]
{没有应用状态模式的代码} //工程文件 program Project1; {$APPTYPE CONSOLE} uses uGumballMachine in 'uGumballMachine. ...
- centos 安装nginx + 多个tomcat负载均衡
今天在centos上安装了两个tomcat和nginx,进行配置.今天记录的只是最基本的实现测试.(不包含使用redis进行session共享) Nginx 是一款轻量级的Web 服务器/反向代理服务 ...
- Redhat/Fedora 或类似系统, 配置网络的工具介绍
在Redhat早期的版本中, 有linuxconf .redhat-config-network .netconfig 等工具: 在Redhat/Fedora 最新的版本有 system-config ...
- 【洛谷】P1880 石子合并
P1880 石子合并 题目描述 在一个园形操场的四周摆放N堆石子,现要将石子有次序地合并成一堆.规定每次只能选相邻的2堆合并成新的一堆,并将新的一堆的石子数,记为该次合并的得分. 试设计出1个算法,计 ...
- CF573E (平衡树)
CF573E 题意概要 给出一个长度为\(n\)的数列,从中选出一个子序列\(b[1...m]\)(可以为空) 使得\[ \sum_{i=1}^m{b_i*i}\]最大,输出这个最大值. 其中\(n\ ...
- OpenLayers在地图外放置控件
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN"> <html> <head ...
- Python 五个知识点搞定作用域
Python 五个知识点搞定作用域 1.块级作用域 想想此时运行下面的程序会有输出吗?执行会成功吗? #块级作用域 if 1 == 1: name = "lzl" print(na ...
- django1.11启动错误
错误信息: 复制代码 Unhandled exception in thread started by <function check_errors..wrapper at 0x10f03b8c ...