发展城市

【问题描述】

众所周知,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. CSS的相对定位和绝对定位

     relative的意思就是相对自己的一开始的位置进行的定位.如图: 但是这个元素的本身边距不变,还在原来位置   absolute的意思就是 如果它的父元素设置了除static之外的定位,比如pos ...

  2. App Store中的开源游戏汇总

    这是国外达人收集的曾经在app store上出现过,或者还在app store上卖的iOS开源游戏的列表,其中代码大部分人你托管在google code或者github上,其中有很多使用Cocos2D ...

  3. IOS音频视频

    视频播放 MediaPlayer.framework MPMoviePlayerViewController VS MPMoviePlayerController MPMoviePlayerViewC ...

  4. 基于Python的Web应用开发实战——2 程序的基本结构

    2.1 初始化 所有Flaks程序都必须创建一个程序实例. Web服务器使用一种名为Web服务器网关接口(Web Server Gateway Interface,WSGI)的协议,把接收自客户端的所 ...

  5. c语言实验7 文件

    part 1 验证性实验 验证性实验1 验证性实验2:已知文本数据文件file1.dat,从中读取数据,找出最高分和最低分学生信息,并输入在屏幕上. 运行结果如下图: #include <std ...

  6. leetcode_day1

    1.给定一个整数数组 nums 和一个目标值 target,请你在该数组中找出和为目标值的那 两个 整数,并返回他们的数组下标. 你可以假设每种输入只会对应一个答案.但是,你不能重复利用这个数组中同样 ...

  7. ERROR 2059 (HY000): Authentication plugin 'caching_sha2_password' cannot be loaded: /usr/lib64/mysql/plugin/caching_sha2_password.so: cannot open shared object file: No such file or directory

    部署docker下的mysql时出现以下报错 [root@docker ~]# mysql -h192.168.30.22 -uroot -p Enter password: 出现报错: ERROR ...

  8. js的正则表达式总结

    1.8-20位数字 or  字母 or 特殊字符 var reg = /^[0-9a-zA-Z!@#$%^&*()_+-/.]{8,20}$/; 2.8-20位 数字+字母+特殊字符 //正则 ...

  9. Java中的日期(Calendar、Date)

    (1)获取当前日期: java.util.Calendar calendar = java.util.Calendar.getInstance(); 或  = new java.util.Gregor ...

  10. LeetCode 最大正方形

    在一个由 0 和 1 组成的二维矩阵内,找到只包含 1 的最大正方形,并返回其面积. 示例: 输入: 1 0 1 0 0 1 0 1 1 1 1 1 1 1 1 1 0 0 1 0 输出: 4解法:判 ...