【BZOJ3700】发展城市 [LCA][RMQ]
发展城市
Time Limit: 20 Sec Memory Limit: 512 MB
[Submit][Status][Discuss]
Description
众所周知,Hzwer学长是一名高富帅,他打算投入巨资发展一些小城市。
Hzwer打算在城市中开N个宾馆,由于Hzwer非常壕,所以宾馆必须建在空中,但是这样就必须建立宾馆之间的连接通道。机智的Hzwer在宾馆中修建了N-1条隧道,也就是说,宾馆和隧道形成了一个树形结构。
Hzwer有时候会花一天时间去视察某个城市,当来到一个城市之后,Hzwer会分析这些宾馆的顾客情况。对于每个顾客,Hzwer用三个数值描述他:(S, T, V)表示该顾客这天想要从宾馆S走到宾馆T,他的速度是V。
Hzwer需要做一些收集一些数据,这样他就可以规划他接下来的投资。
其中有一项数据就是收集所有顾客可能的碰面次数。
每天清晨,顾客同时从S出发以V的速度前往T(注意S可能等于T),当到达了宾馆T的时候,顾客显然要找个房间住下,那么别的顾客再经过这里就不会碰面了。特别的,两个顾客同时到达一个宾馆是可以碰面的。同样,两个顾客同时从某宾馆出发也会碰面。
Input
第一行一个正整数T(1<=T<=20),表示Hzwer发展了T个城市,并且在这T个城市分别视察一次。
对于每个T,第一行有一个正整数N(1<=N<=10^5)表示Hzwer在这个城市开了N个宾馆。
接下来N-1行,每行三个整数X,Y,Z表示宾馆X和宾馆Y之间有一条长度为Z的隧道
再接下来一行M表示这天顾客的数量。
紧跟着M行每行三个整数(S, T, V)表示该顾客会从宾馆S走到宾馆T,速度为v
Output
对于每个T,输出一行,表示顾客的碰面次数。
Sample Input
3
1 2 1
2 3 1
3
1 3 2
3 1 1
1 2 3
1
0
Sample Output
0
HINT
1<=T<=20 1<=N<=10^5 0<=M<=10^3 1<=V<=10^6 1<=Z<=10^3
Main idea
给定若干个顾客,每个顾客会匀速从一个点走到另外一个点,问有几对人会在路上相遇。
Solution
由于人数较少,所以我们可以O(m^2)判断两人是否相交。
首先,两个人相遇只可能是在路径重叠的部分相遇,所以我们先对两人的路径求交,这里提供一种对树上路径求交的方法:
求出AB两人路径的交:
设A路径为a.u->a.v,B路径为b.u->b.v。那么我们求出 LCA(a.u,b.u),LCA(a.v,b.v),LCA(a.u,b.v),LCA(b.u,a.v),然后保留下在AB路径上的点。(判断一个点是否在路径上:若u在LCA(x,y)的子树中,且u为LCA(u,x)或者LCA(u,y),则u在路径x,y上),然后按照dfs序位置排序,去重,保留下后两个点,则后两个点即是路径的端点。
但是这样求交的话需要多次查询LCA,我们用每次log的时间查询显然会超时,于是我们引进O(nlog(n))预处理,O(1)查询的LCA。
O(1)查询的LCA:
我们先求出对于这棵树的欧拉序(欧拉序:记下每个点第一次访问的位置以及回溯完的位置),然后我们用那么这时候x,y之间的LCA也就是 [pos[x],pos[y]] 区间内深度最小的点(pos[x]表示点x第一次在欧拉序中出现的位置),这个区间最小值用RMQ求即可。
现在我们已经求出了路径的交集,然后我们暴力分类讨论一下。如果没有交集则必然不相交,若交于一点判断一下到达时间即可,否则:
先考虑两人运动的方向。我们记录p.u,p.v表示路径交集的两个端点。A1表示A到先进入路径的端点,A2表示A后到的端点,B1、B2类似(用距离长短判断即可),如果A1=B1则表示两人同向运动,否则表示相向运动。然后我们讨论一下:
同向运动:如果两人同向运动,那么若先进入路径的后离开路径,则两人会相遇。
相向运动:如果两人相向运动,则我们记录到端点的时间,如果两个人在路径上的时间有交集的话,则会相遇。
然后这样判断一下就可以求出答案了,但是由于double定义下的除法速度很慢,会被卡常数,所以我们再用在long long定义下的交叉相乘来判断以上情况。这样我们就解决了这道题\(≧▽≦)/
Code
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<cmath>
using namespace std;
typedef long long s64; const int ONE = ; int T;
int n,m;
int x,y,z;
int next[ONE*],first[ONE],go[ONE*],w[ONE*],tot;
int pos[ONE],dfn_cnt,Dep[ONE],size[ONE];
int MinD[ONE*][],NumD[ONE*][];
int Log[ONE*],Bin[];
int Stk[],top,fc;
int Ans;
s64 d[ONE]; struct power
{
int u,v;
int val;
}a[],p; namespace input
{
const int BufferSize = << | ; char buffer[BufferSize];
char *head = buffer + BufferSize;
const char *tail = head; inline char nextChar()
{
if (head == tail)
{
fread(buffer, , BufferSize, stdin);
head = buffer;
}
return *head++;
} inline int get()
{
static char c;
while ((c = nextChar()) < '' || c > ''); int res = c - '';
while ((c = nextChar()) >= '' && c <= '')
res = res * + c - '';
return res;
}
}
using input::get; inline void Add(int u,int v,int z)
{
next[++tot]=first[u]; first[u]=tot; go[tot]=v; w[tot]=z;
next[++tot]=first[v]; first[v]=tot; go[tot]=u; w[tot]=z;
} namespace F
{
int Dfs(int u,int father)
{
pos[u] = ++dfn_cnt;
Dep[u] = Dep[father] + ;
size[u] = ;
MinD[dfn_cnt][]=Dep[u]; NumD[dfn_cnt][]=u;
for(int e=first[u];e;e=next[e])
{
int v=go[e];
if(v==father) continue;
d[v] = d[u] + w[e];
Dep[v] = Dep[u] + ;
Dfs(v,u);
size[u] += size[v];
MinD[++dfn_cnt][]=Dep[u]; NumD[dfn_cnt][]=u;
}
} inline void Pre_Rmq()
{
for(int j=;j<=;j++)
for(int i=;i<=dfn_cnt;i++)
if(i+Bin[j]- <= dfn_cnt)
{
int Next = i + Bin[j-];
if(MinD[i][j-] < MinD[Next][j-])
MinD[i][j]=MinD[i][j-], NumD[i][j]=NumD[i][j-];
else
MinD[i][j]=MinD[Next][j-], NumD[i][j]=NumD[Next][j-];
}
else break;
}
} inline int LCA(int x,int y)
{
x=pos[x]; y=pos[y];
if(x > y) swap(x,y);
int T = Log[y - x +];
if(MinD[x][T] < MinD[y-Bin[T]+][T]) return NumD[x][T];
return NumD[y-Bin[T]+][T];
} inline s64 dist(int x,int y)
{
return d[x] + d[y] - (d[LCA(x,y)] << ) ;
} namespace PD
{
inline bool inroad(int u,power a)
{
int lca = LCA(a.u,a.v);
if(LCA(u,lca) != lca) return ;
return (LCA(u,a.u)==u || LCA(u,a.v)==u);
}
} inline void Sort(int n)
{
for(int i=;i<=n;i++)
for(int j=i+;j<=n;j++)
if(pos[Stk[i]] > pos[Stk[j]])
swap(Stk[i], Stk[j]);
} inline power Get_road(power a,power b)
{
fc=top=;
Stk[++fc] = LCA(a.u,b.u); Stk[++fc] = LCA(a.v,b.v);
Stk[++fc] = LCA(a.u,b.v); Stk[++fc] = LCA(b.u,a.v);
for(int i=;i<=fc;i++)
if(PD::inroad(Stk[i],a) && PD::inroad(Stk[i],b))
Stk[++top] = Stk[i]; Sort(top);
top=unique(Stk+,Stk+top+) - Stk - ; power p; p.val = ;
if(top==) p.u = p.v = ;
if(top==) p.u = p.v = Stk[];
if(top==) p.u=Stk[], p.v=Stk[];
if(top==) p.u=Stk[], p.v=Stk[];
return p;
} inline bool pmin(s64 a,s64 b,s64 c)
{
if(a<=b && b<=c) return ;
return ;
} inline int Deal(int x,int y)
{
if(a[x].u == a[y].u) return ;
p = Get_road(a[x],a[y]);
if(p.u==p.v)
{
if(!p.u) return ;
return (s64) dist(a[x].u,p.u) * a[y].val == (s64) dist(a[y].u,p.u) * a[x].val;
} int A1,A2,B1,B2;
double A1_time,A2_time,B1_time,B2_time;
if(dist(a[x].u,p.u) < dist(a[x].u,p.v)) A1=p.u, A2=p.v;else A1=p.v, A2=p.u;
if(dist(a[y].u,p.u) < dist(a[y].u,p.v)) B1=p.u, B2=p.v;else B1=p.v, B2=p.u; A1_time=(s64)dist(A1,a[x].u)*a[y].val; A2_time=(s64)dist(A2,a[x].u)*a[y].val;
B1_time=(s64)dist(B1,a[y].u)*a[x].val; B2_time=(s64)dist(B2,a[y].u)*a[x].val; if(A1==B1)//same
{
if(A1_time == B1_time) return ;
if(A1_time < B1_time) return A2_time >= B2_time;
return A2_time <= B2_time;
}
else
{
if(pmin(A1_time,B1_time,A2_time)) return ;
if(pmin(A1_time,B2_time,A2_time)) return ;
if(pmin(B1_time,A1_time,B2_time)) return ;
if(pmin(B1_time,A2_time,B2_time)) return ;
return ;
}
} inline void Solve()
{
n=get();
dfn_cnt=tot=;
memset(first,,sizeof(first));
for(int i=;i<n;i++)
{
x=get(); y=get(); z=get();
Add(x,y,z);
} F::Dfs(,); F::Pre_Rmq(); m=get();
for(int i=;i<=m;i++)
{
a[i].u=get(); a[i].v=get(); a[i].val=get();
} Ans = ; for(int i=;i<=m;i++)
for(int j=i+;j<=m;j++)
{
Ans += Deal(i,j);
} printf("%d\n",Ans);
} int main()
{
Log[]=-; for(int i=;i<=2e5;i++) Log[i] = Log[i>>] + ;
Bin[]=; for(int i=;i<=; i++) Bin[i] = Bin[i-] << ; T=get(); while(T--)
Solve();
}
【BZOJ3700】发展城市 [LCA][RMQ]的更多相关文章
- BZOJ3700: 发展城市
BZOJ3700: 发展城市 https://lydsy.com/JudgeOnline/problem.php?id=3700 分析: 枚举两个人,先求链交,求到两个端点的时间. 链交求法:求两两\ ...
- BZOJ1906树上的蚂蚁&BZOJ3700发展城市——RMQ求LCA+树链的交
题目描述 众所周知,Hzwer学长是一名高富帅,他打算投入巨资发展一些小城市. Hzwer打算在城市中开N个宾馆,由于Hzwer非常壕,所以宾馆必须建在空中,但是这样就必须建立宾馆之间的连接通道.机智 ...
- 发展城市 BZOJ 3700
发展城市 [问题描述] 众所周知,Hzwer学长是一名高富帅,他打算投入巨资发展一些小城市. Hzwer打算在城市中开N个宾馆,由于Hzwer非常壕,所以宾馆必须建在空中,但是这样就必须建立宾馆之间的 ...
- 【Homework】LCA&RMQ
我校是神校,作业竟然选自POJ,难道不知道“珍爱生命 勿刷POJ”么? 所有注明模板题的我都十分傲娇地没有打,于是只打了6道题(其实模板题以前应该打过一部分但懒得找)(不过感觉我模板还是不够溜要找个时 ...
- POJ 2763 (LCA +RMQ+树状数组 || 树链部分) 查询两点距离+修改边权
题意: 知道了一颗有 n 个节点的树和树上每条边的权值,对应两种操作: 0 x 输出 当前节点到 x节点的最短距离,并移动到 x 节点位置 1 x val 把第 x 条边的权值改为 ...
- 算法详解(LCA&RMQ&tarjan)补坑啦!完结撒花(。◕ˇ∀ˇ◕)
首先,众所周知,求LCA共有3种算法(树剖就不说了,太高级,以后再学..). 1.树上倍增(ST表优化) 2.RMQ&时间戳(ST表优化) 3.tarjan(离线算法)不讲..(后面补坑啦!) ...
- 牛客小白月赛13 小A的最短路(lca+RMQ)
链接:https://ac.nowcoder.com/acm/contest/549/F来源:牛客网 题目描述 小A这次来到一个景区去旅游,景区里面有N个景点,景点之间有N-1条路径.小A从当前的一个 ...
- UESTC 912 树上的距离 --LCA+RMQ+树状数组
1.易知,树上两点的距离dis[u][v] = D[u]+D[v]-2*D[lca(u,v)] (D为节点到根节点的距离) 2.某条边<u,v>权值一旦改变,将会影响所有以v为根的子树上的 ...
- [LCA & RMQ] [NOIP2013] 货车运输
首先看到这题, 由于要最大, 肯定是求最大生成树 那么 o(n2) dfs 求任意点对之间的最小边是可以想到的 但是看看数据范围肯定TLE 于是暴力出来咯, 不过要注意query的时候判断的时候要 m ...
随机推荐
- 程序员编程利器:20款最好的免费的IDEs和编辑器
程序员编程利器:20款最好的免费的IDEs和编辑器 还没转眼明年可就大年三十了,忙的可真是晕头转了个向,看着亲朋好友们那让人欣羡的小肚腩,不禁感慨,岁月是一把猪饲料,绿了芭蕉,肥了那杨柳小蛮腰,可怜我 ...
- 「暑期训练」「Brute Force」 Far Relative’s Problem (CFR343D2B)
题意 之后补 分析 我哭了,强行增加自己的思考复杂度...明明一道尬写的题- -(往区间贪心方向想了 其实完全没必要,注意到只有366天,直接穷举判断即可. 代码 #include <bits/ ...
- linux学习总结---web前端③
css3: border-radius opacity: transform: 旋转 rotate 平移translate 缩放scale 扭曲skew transition:转变 强调:开始和结束 ...
- Mysql性能优化一:SQL语句性能优化
这里总结了52条对sql的查询优化,下面详细来看看,希望能帮助到你 1, 对查询进行优化,应尽量避免全表扫描,首先应考虑在 where 及 order by 涉及的列上建立索引. 2,应尽量避免在 w ...
- 切换pip源的简便方法
网上大部分帖子讲的都是打开配置文件修改,那样太麻烦了,其实只要一行命令搞定: pip config set global.index-url https://pypi.tuna.tsinghua.ed ...
- Week7 Teamework from Z.XML-NABC
NABC 引言:我们团队计划做一个手机端的类RPG2d游戏.之所以我们定义为类RPG,是因为我们希望弱化RPG在游戏中的概念--减少或者排除人物对话等较为无趣的内容,而将重点放在玩家的娱乐享受中.为了 ...
- 给曾经是phper的程序员推荐个学习网站
如果你原来是一个php程序员,你对于php函数非常了解(PS:站长原来就是一个php程序员),但是现在由于工作或者其他原因要学习python,但是python很多函数我们并不清楚,在这里我给大家推荐一 ...
- angular2采用自定义指令(Directive)方式加载jquery插件
由于angular2兴起不久,相关插件还是很少,所以有时候不得不用一些jquery插件来完成项目, 那么如何把jquery插件放到angular2中呢?采用自定义指令! 在上下文之前要引入jquery ...
- HDU I-最少拦截系统
http://acm.hdu.edu.cn/showproblem.php?pid=1257 Problem Description 某国为了防御敌国的导弹袭击,发展出一种导弹拦截系统.但是这种导弹拦 ...
- DataGridView过滤功能
http://www.codeproject.com/Articles/33786/DataGridView-Filter-Popup http://www.cnblogs.com/jaxu/arch ...