发展城市

【问题描述】

众所周知,Hzwer学长是一名高富帅,他打算投入巨资发展一些小城市。

Hzwer打算在城市中开N个宾馆,由于Hzwer非常壕,所以宾馆必须建在空中,但是这样就必须建立宾馆之间的连接通道。机智的Hzwer在宾馆中修建了N-1条隧道,也就是说,宾馆和隧道形成了一个树形结构。

Hzwer有时候会花一天时间去视察某个城市,当来到一个城市之后,Hzwer会分析这些宾馆的顾客情况。对于每个顾客,Hzwer用三个数值描述他:(S, T, V)表示该顾客这天想要从宾馆S走到宾馆T,他的速度是V。

Hzwer需要做一些收集一些数据,这样他就可以规划他接下来的投资。

其中有一项数据就是收集所有顾客可能的碰面次数。

每天清晨,顾客同时从S出发以V的速度前往T(注意S可能等于T),当到达了宾馆T的时候,顾客显然要找个房间住下,那么别的顾客再经过这里就不会碰面了。特别的,两个顾客同时到达一个宾馆是可以碰面的。同样,两个顾客同时从某宾馆出发也会碰面。

【输入格式】

第一行一个正整数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

【输出格式】

对于每个T,输出一行,表示顾客的碰面次数。

【样例输入】

1

3

1 2 1

2 3 1

3

1 3 2

3 1 1

1 2 3

1

0

【样例输出】

2

0

【数据规模】

1<=T<=20   1<=N<=10^5   0<=M<=10^3   1<=V<=10^6   1<=Z<=10^3


题解:

题意就是求两两树上路径是否能在相交路径上相遇

求相交路径自然就要求出最近公共祖先

╰( ̄▽ ̄)╭为了卡常数,使用O(1)求Lca的方法(当然,某位dalao用了O(log2(n))的树剖,并真的好像跑得确实稍微快那么一点~~~)

首先处理出树的欧拉序列(就是把每个点入栈和出栈记录下来,那么两个点的Lca就是它们组成的区间中深度最小的点)

用Rmq处理区间最值和对应的点就好啦

有了Lca,两个点的距离自然好求

那么我们就解决了问题的子问题的子问题的两个子问题啦

先考虑如何求出在一条路径上与某个点距离最近的点,记为Closest(a,b,c)

假设我们要求出(a,b)路径上的距离c最近的点

记x=Lca(a,b),y=Lca(c,a),z=Lca(c,b)

首先如果c不在x的子树内,由于树上最近路径唯一,x就是在(a,b)路径上与c最近的点

否则如果y不为x,这说明c和a同时属于x某个孩子的子树,那么y就是最近点,z同理

再否则说明a,b,c分属x三个孩子的子树,那么x还是最近点

至此我们解决了求路径上与点最近的点的问题

我们再来考虑如何求出两条路径的交这个子问题(对,没错,上面那个就是子问题的子问题,也是问题的子问题)

如果两条路径有交,那么第一条路径的两个点与第一条路径的两个最近点组成的路径必定与第二条路径的两个点与第一条路径的两个最近点组成的路径相等

有点点长(不是打错了(废话好多(自己吐槽是什么鬼))),冗长的自然语言啊

记两条路径为(a,b)和(c,d)

记abc为Close(a,b,c),其他同理

那么(abc,abd)=(cda,cdb)(这是无序的)

又一个问题解决了

最后考虑是否相遇

起点相同啊,没有相交路径啊,相交路径只有一个点啊,这些判一判就好啦

设两个人为x,y

设相交路径为u,v

设两条路径(两个人)的起点、终点为sx,tx,sy,ty

记Time(x,y)为x为起点,y为终点,以以x为起点的人的速度为速度所需的时间(再次重申没有打错)

求相遇当然要判断同向异向,判断的话考虑Closest(u,v,sx)是否等于Closest(u,v,sy),两个的含义分别是求两个点在相交路径上的起点,剩下的就显而易见了

为了方便,取u为x在(u,v)上的起点

异向的话只要满足一个在到达起点时另一个还未达到终点,那么它们必定相遇,判断就是Time(sx,u)<=Time(sy,u)且Time(sy,v)<=Time(sx,v)

同向的话只要满足先到达起点的后到达终点就行了,判断就看代码实现吧

求时间的话要用double啥的

由于我们只要求大小关系,交叉相乘即可

至此我们结束了整个问题(os:怎么这么长~~~~~~)

其实我是%了黄学长代码的<(* ̄▽ ̄*)/(那你还bb这么多)

 #include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdlib>
#include<cstdio>
#include<cmath>
using namespace std;
const int logn = ;
const int maxn = ;
int lea[maxn][logn], dot[maxn][logn];
int num, pos[maxn], dfn[maxn], dep[maxn];
long long dis[maxn];
int tot, nex[maxn], fir[maxn], ver[maxn], val[maxn];
int powe[logn], loga[maxn];
int T;
int n, m;
int x, y, z;
int ans;
int s[maxn], t[maxn], vel[maxn];
struct couple
{
int x, y;
};
inline void Scan(int &x)
{
char c;
bool o = false;
while((c = getchar()) < '' || c > '')
if(c == '-') o = true;
x = c - '';
while((c = getchar()) >= '' && c <= '')
x = x * + c - '';
x = (o) ? -x : x;
}
inline void Clear()
{
tot = num = ans = ;
for(int i = ; i <= n; ++i) fir[i] = ;
}
inline void Ins(int x, int y, int z)
{
nex[++tot] = fir[x];
fir[x] = tot;
ver[tot] = y;
val[tot] = z;
}
inline void Table()
{
powe[] = ;
loga[] = ;
for(int i = ; i < logn; ++i) powe[i] = powe[i - ] << , loga[powe[i]] = ;
for(int i = ; i < maxn; ++i) loga[i] += loga[i - ];
}
inline void Rmq()
{
for(int i = ; i <= num; ++i)
{
dot[i][] = dfn[i];
lea[i][] = dep[dfn[i]];
}
for(int j = ; j <= loga[num] + ; ++j)
for(int i = ; i <= num; ++i)
{
int k = i + powe[j - ];
if(k >= num) continue;
if(lea[i][j - ] < lea[k][j - ])
{
lea[i][j] = lea[i][j - ];
dot[i][j] = dot[i][j - ];
}
else
{
lea[i][j] = lea[k][j - ];
dot[i][j] = dot[k][j - ];
}
}
}
inline int Lca(int x, int y)
{
x = pos[x], y = pos[y];
if(x > y) swap(x, y);
int len = loga[y - x + ];
int mid = y - powe[len] + ;
if(lea[x][len] < lea[mid][len]) return dot[x][len];
return dot[mid][len];
}
inline long long Dis(int x, int y)
{
return dis[x] + dis[y] - (dis[Lca(x, y)] << );
}
void Dfs(int u, int f)
{
pos[u] = ++num;
dfn[num] = u;
for(int i = fir[u]; i; i = nex[i])
{
int v = ver[i];
if(v == f) continue;
dep[v] = dep[u] + ;
dis[v] = dis[u] + val[i];
Dfs(v, u);
dfn[++num] = u;
}
}
inline int Close(int a, int b, int c)
{
int x = Lca(a, b);
if(x != Lca(x, c)) return x;
int y = Lca(a, c);
if(x != y) return y;
int z = Lca(b, c);
if(x != z) return z;
return x;
}
inline couple Path(int a, int b, int c, int d)
{
int abc = Close(a, b, c);
int abd = Close(a, b, d);
int cda = Close(c, d, a);
int cdb = Close(c, d, b);
if(abc > abd) swap(abc, abd);
if(cda > cdb) swap(cda, cdb);
if(abc == cda && abd == cdb) return (couple) {abc, abd};
return (couple) {-, -};
}
inline bool Meet(int x, int y)
{
if(s[x] == s[y]) return true;
couple z = Path(s[x], t[x], s[y], t[y]);
int u = z.x, v = z.y;
if(u < ) return false;
if(u == v) return Dis(s[x], u) * vel[y] == Dis(s[y], u) * vel[x];
if(Close(u, v, s[x]) == v) swap(u, v);
if(Close(u, v, s[x]) != Close(u, v, s[y]))
{
bool fa = Dis(s[x], u) * vel[y] <= Dis(s[y], u) * vel[x];
bool fb = Dis(s[x], v) * vel[y] >= Dis(s[y], v) * vel[x];
return fa && fb;
}
long long a = Dis(s[x], u) * vel[y];
long long b = Dis(s[y], u) * vel[x];
if(a == b) return true;
if(a > b) swap(x, y);
return Dis(s[x], v) * vel[y] >= Dis(s[y], v) * vel[x];
}
int main()
{
memset(lea, , sizeof(lea));
Table();
Scan(T);
while(T--)
{
Clear();
Scan(n);
for(int i = ; i < n; ++i)
{
Scan(x), Scan(y), Scan(z);
Ins(x, y, z);
Ins(y, x, z);
}
Dfs(, );
Rmq();
Scan(m);
for(int i = ; i <= m; ++i) Scan(s[i]), Scan(t[i]), Scan(vel[i]);
for(int i = ; i <= m; ++i)
for(int j = i + ; j <= m; ++j)
ans += Meet(i, j);
printf("%d\n", ans);
}
}

发展城市 BZOJ 3700的更多相关文章

  1. BZOJ3700: 发展城市

    BZOJ3700: 发展城市 https://lydsy.com/JudgeOnline/problem.php?id=3700 分析: 枚举两个人,先求链交,求到两个端点的时间. 链交求法:求两两\ ...

  2. 【BZOJ3700】发展城市 [LCA][RMQ]

    发展城市 Time Limit: 20 Sec  Memory Limit: 512 MB[Submit][Status][Discuss] Description 众所周知,Hzwer学长是一名高富 ...

  3. BZOJ1906树上的蚂蚁&BZOJ3700发展城市——RMQ求LCA+树链的交

    题目描述 众所周知,Hzwer学长是一名高富帅,他打算投入巨资发展一些小城市. Hzwer打算在城市中开N个宾馆,由于Hzwer非常壕,所以宾馆必须建在空中,但是这样就必须建立宾馆之间的连接通道.机智 ...

  4. bzoj AC倒序

    Search GO 说明:输入题号直接进入相应题目,如需搜索含数字的题目,请在关键词前加单引号 Problem ID Title Source AC Submit Y 1000 A+B Problem ...

  5. 拓扑排序 --- hdu 4948 : Kingdom

    Kingdom Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Sub ...

  6. [Arduino] 基于Xbee Pro和网络技术的智能公交系统设计

    转自:http://www.21ic.com/app/rf/201112/99474.htm 引言 公共交通具有个体交通无法比拟的强大优势,优先发展城市公共交通系统是解决大.中城市交通问题的最佳途径. ...

  7. 2015年iOS开发工程师前景分析

    "互联网+"概念的提出催生了大量互联网企业,越来越多的传统行业需要与互联网更深地渗透与融合.而在这股互联网化的浪潮中,行业却发现找不到优秀的互联网人才. 互联网企业数量持续增长,用 ...

  8. dsu on tree:关于一类无修改询问子树可合并问题

    dsu on tree:关于一类无修改询问子树可合并问题 开始学长讲课的时候听懂了但是后来忘掉了....最近又重新学了一遍 所谓\(dsu\ on\ tree\)就是处理本文标题:无修改询问子树可合并 ...

  9. Ming Yin(@kalasoo)在知乎的几个回答 : 观点犀利

    这篇文章汇总了掘金前站长Ming Yin(阴明)在知乎的几个犀利的观点,原文可访问zhihu.com/kalasoo 由@flightmakers转载(收藏)在此 你是否有个人网站.可否和大家分享一下 ...

随机推荐

  1. Python 学习日志9月19日

    9月19日 周二 今天是普通的一天,昨天也是普通的一天,刚才我差点忘记写日志,突然想起来有个事情没做,回来写. 今天早晨学习<Head First HTML and CSS>第十一章节“布 ...

  2. Web开发者必须知道的10个jQuery代码片段

    在过去的几年中,jQuery一直是使用最为广泛的JavaScript脚本库.今天我们将为各位Web开发者提供10个最实用的jQuery代码片段,有需要的开发者可以保存起来. 1.检测Internet ...

  3. Java的jdbc调用SQL Server存储过程Bug201906131119

    SQL Server数据库存储过程,一个查询使用动态sql,另一个不使用动态sql,这种情况,jdbc可能获取不到实际查询数据,虽然数据库中执行没问题. 解决方法,都使用静态sql,或都使用动态sql ...

  4. Pacman常用命令 文内搜索吧

    列出已经安装的软件包 https://wiki.archlinux.org/index.php/Pacman_(%E7%AE%80%E4%BD%93%E4%B8%AD%E6%96%87)  维基 pa ...

  5. C++模板 · 为什么要引入模板机制?

    刚学过类模板时,很不理解,甚至觉得这简直没有用,在自己骗自己嘛!明明很方便的东西,偏偏要加个类模板来回折腾.可能因为我们刚开始写的程序很简单,有时候,可能程序复杂一点,对理解一些概念更有帮助. 今天在 ...

  6. emoji等表情符号存mysql的方法

    项目中需要存储用户信息(用户昵称有表情符号),自然就遇到了emoji等表情符号如何被mysql DB支持的问题 这里引用先行者博文:https://segmentfault.com/a/1190000 ...

  7. 验证debug思路之从寄存器开始

    对于boot a peripherial or module 一般都是配置一系列的寄存器(有可能有时间等方便的写入读出要求). 1.确保寄存器的读写按spec要求完成.<====可以通过波形查看 ...

  8. 【linux】【git】安装/升级Git 1.9.4

      因为yum源的最新版本是1.7.x,所以无法通过yum进行更新,下面描述如何通过编译源码进行安装 1.安装需要的依赖 第一步我们需要做的就是确认系统已经安装了编译git时需要的依赖.使用下面的安装 ...

  9. 关于json的dump和dumps

    首先说明基本功能: dumps是将dict转化成str格式,loads是将str转化成dict格式. dump和load也是类似的功能,只是与文件操作结合起来了. 1.把python的数据,转换为js ...

  10. LeetCode(91) Decode Ways

    题目 A message containing letters from A-Z is being encoded to numbers using the following mapping: 'A ...