meet

大概思路就是 , 找出相交的路径 , 判断方向 , 分类讨论。。

假设已经找出了相交路径 。。。

若方向相同 , 则找到相交路径上边权的最大值 , 若最大值>出发时间差 , 则可行。

原因: 由于方向相同所以在相交路径上这两个点的相对距离是不变的,看最大的边权即可。

这个东西用st表就可以搞定

若方向不同,就看看他们相遇的位置是不是相交路径上各个(不一定是最两头的点)边的端点之一。

因为题中说在边上才算 , 点不能算到边上。 所以不在点上就一定会在边上相遇。

然后就是怎么找相交路径了。。

大概有这么几种情况。。

分类讨论即可

#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<vector>
#include<cmath>
#include<queue>
#include<set>
#include<map>
using namespace std;
#define int long long
const int N = 1e5+10;
inline int read()
{
register int x = 0 , f = 0; register char c = getchar();
while(c < '0' || c > '9') f |= c == '-' , c = getchar();
while(c >= '0' && c <= '9') x = (x << 3) + (x << 1) + c - '0' , c = getchar();
return f ? -x : x;
}
int n , Q , cnt;
int head[N] , f[N][20] , st[N][20] , pre[N] , d[N] , dis[N] , Log[N];
struct edge{ int v , nex , c , id; } e[N<<1];
struct node{
int id , l , r;
node(int id = 0 , int l = 0 , int r = 0) : id(id) , l(l) , r(r) {}
} A[N] , B[N];
inline void add(int u , int v , int c , int id) { e[++cnt].v = v; e[cnt].nex = head[u]; e[cnt].c = c; e[cnt].id = id; head[u] = cnt; return ; } void dfs(int x , int fa)
{
f[x][0] = fa; d[x] = d[fa] + 1;
for(int i = 1 ; i < 20 ; ++i) f[x][i] = f[f[x][i-1]][i-1] , st[x][i] = max(st[x][i-1] , st[f[x][i-1]][i-1]);
for(int i = head[x] , v ; i ; i = e[i].nex)
{
v = e[i].v; if(v == fa) continue;
pre[v] = i; st[v][0] = e[i].c; dis[v] = dis[x] + e[i].c; dfs(v , x);
}
return ;
} int LCA(int x , int y)
{
if(d[x] < d[y]) swap(x , y);
for(int i = 19 ; ~i ; --i) if(d[f[x][i]] >= d[y]) x = f[x][i];
if(x == y) return x;
for(int i = 19 ; ~i ; --i) if(f[x][i] != f[y][i]) x = f[x][i] , y = f[y][i];
return f[x][0];
} void Work(int u , int v , int t , int &tot , node *s)
{
int p = LCA(u , v);
while(u != p)
{
int i = pre[u];
s[++tot] = node(e[i].id , t , t + e[i].c);
t += e[i].c; u = f[u][0];
}
int lim = tot , T = 0;
while(v != p)
{
int i = pre[v];
s[++tot] = node(e[i].id , T , T + e[i].c);
T += e[i].c; t += e[i].c; v = f[v][0];
}
for(int i = lim + 1 ; i <= tot ; ++i) s[i].l = t - s[i].l , s[i].r = t - s[i].r , swap(s[i].l , s[i].r);
return ;
} inline bool cmp(const node &A , const node &B) { return A.id < B.id; } void solve1()
{
for(int i = 1 ; i <= n ; ++i) d[i] = 0;
dfs(1 , 0);
int u1 , v1 , t1 , u2 , v2 , t2 , tot1 , tot2;
while(Q--)
{
u1 = read(); v1 = read(); t1 = read(); tot1 = 0;
u2 = read(); v2 = read(); t2 = read(); tot2 = 0;
Work(u1 , v1 , t1 , tot1 , A);
Work(u2 , v2 , t2 , tot2 , B);
sort(A + 1 , A + 1 + tot1 , cmp);
sort(B + 1 , B + 1 + tot2 , cmp);
int l = 1 , r = 1 , flag = 0;
while(l <= tot1 && r <= tot2)
{
if(A[l].id < B[r].id) l++;
else if(A[l].id > B[r].id) r++;
else
{
if((A[l].l <= B[r].l && B[r].l < A[l].r) || (A[l].l < B[r].r && B[r].r <= A[l].r)) { flag = 1; break; }
l++; r++;
}
}
puts(flag ? "YES" : "NO");
}
return ;
} int Ask_MAX(int x , int y) // 求得x->y之间边权的最大值
{
int ans = 0;
if(d[x] < d[y]) swap(x , y);
for(int i = 19 ; ~i ; --i) if(d[f[x][i]] >= d[y]) ans = max(ans , st[x][i]) , x = f[x][i];
if(x == y) return ans;
for(int i = 19 ; ~i ; --i) if(f[x][i] != f[y][i]) ans = max(ans , max(st[x][i] , st[y][i])) , x = f[x][i] , y = f[y][i];
return max(ans , max(st[x][0] , st[y][0]));
} inline int Abs(int x) { return x < 0 ? -x : x; } #define stop { puts("NO"); return ; }
#define is_ok { puts("YES"); return ; }
void calc0(int x , int y , int t1 , int t2) // 同向
{
if(x == y) stop
int Max = Ask_MAX(x , y);
puts(Abs(t1 - t2) < Max ? "YES" : "NO");
return ;
} int find(int x , int s) // x 往上走 s 到达的点是不是整点
{
s = dis[x] - s;
for(int i = 19 ; ~i ; --i) if(dis[f[x][i]] >= s) x = f[x][i];
return dis[x] == s;
} void calc1(int x , int y , int t1 , int t2)
{
if(x == y) stop
int p = LCA(x , y) , s = dis[x] + dis[y] - 2 * dis[p] , S = s + t2 - t1; // 这里的S是用来算x要走多少
if(S < 0 || S > 2 * s) stop
if(S & 1) is_ok
S >>= 1; int ans = 0; // 这是真正x要走多少 , 上面那个意会。。
if(dis[x] - dis[p] >= S) ans = find(x , S); else ans = find(y , s - S);
puts(ans ? "NO" : "YES"); return ; } void solve2()
{
dfs(1 , 0); int x1 , y1 , x2 , y2 , t1 , t2 , lx1x2 , ly1y2 , lx1y1 , lx2y2 , lx1y2 , ly1x2;
// 各种LCA 很清楚吧
while(Q--)
{
x1 = read(); y1 = read(); t1 = read();
x2 = read(); y2 = read(); t2 = read();
lx1y1 = LCA(x1 , y1); lx2y2 = LCA(x2 , y2);
if(d[lx1y1] > d[lx2y2]) // 让x1y1的LCA在上面
swap(x1 , x2), swap(y1 , y2), swap(t1 , t2), swap(lx1y1 , lx2y2); lx1x2 = LCA(x1 , x2); ly1y2 = LCA(y1 , y2); // 这个要写下面, 不然会GG
lx1y2 = LCA(x1 , y2); ly1x2 = LCA(y1 , x2);
if(lx1y1 == lx2y2) // 图1
{
if(lx1x2 == lx1y1 && ly1y2 == lx1y1)
calc1(lx1y2 , ly1x2 , t1 + dis[x1] - dis[lx1y2] , t2 + dis[x2] - dis[ly1x2]); // 图1-1
else
calc0(lx1x2 , ly1y2 , t1 + dis[x1] - dis[lx1x2] , t2 + dis[x2] - dis[lx1x2]); // 1-2
continue;
}
int lca = LCA(lx1y1 , lx2y2);
if(lca != lx1y1) { puts("NO"); continue; } // 两条路径不相交
if(LCA(x1 , lx2y2) == lx2y2) // 2
{
if(lx1x2 == lx2y2)
calc1(lx1y2 , lx2y2 , t1 + dis[x1] - dis[lx1y2] , t2 + dis[x2] - dis[lx2y2]); //2-1
else
calc0(lx1x2 , lx2y2 , t1 + dis[x1] - dis[lx1x2] , t2 + dis[x2] - dis[lx1x2]); //2-2
continue;
}
if(LCA(y1 , lx2y2) == lx2y2) // 3
{
if(ly1y2 == lx2y2)
calc1(lx2y2 , ly1x2 , t1 + dis[x1] + dis[lx2y2] - dis[lca] * 2 , t2 + dis[x2] - dis[ly1x2]); // 3-1
else
calc0(lx2y2 , ly1y2 , t1 + dis[x1] + dis[lx2y2] - dis[lca] * 2 , t2 + dis[x2] - dis[lx2y2]); // 3-2
continue;
}
puts("NO");
}
return ;
} signed main()
{
freopen("meet.in" , "r" , stdin);
freopen("meet.out" , "w" , stdout);
n = read(); Q = read();
for(int i = 1 , u , v , c ; i < n ; ++i) u = read() , v = read() , c = read() , d[u]++ , d[v]++ , add(u , v , c , i) , add(v , u , c , i);
if(n <= 100) solve1(); else solve2();
fclose(stdin); fclose(stdout);
return 0;
}
/*
8 6
1 2 3
1 3 1
1 4 2
2 5 5
2 6 1
5 7 2
5 8 4
5 3 2 7 4 2
8 6 1 1 7 6
4 5 1 4 5 10
7 8 3 3 4 5
6 7 6 5 1 2
2 1 10 8 3 3
*/

2019.2.21 T2题解的更多相关文章

  1. kick start 2019 round D T2题解

    题目大意:由N个房子围成一个环,G个人分别顺时针/逆时针在房子上走,一共走M分钟,每分钟结束,每个人顺/逆时针走到相邻的房子.对于每个房子都会记录最后时刻到达的人(可能是一群人).最终输出每个人会被几 ...

  2. 2019.3.18考试&2019.3.19考试&2019.3.21考试

    2019.3.18 C O D E T1 树上直接贪心,环上for一遍贪心 哇说的简单,码了将近一下午终于码出来了 感觉自己码力/写题策略太糟糕了,先是搞了一个细节太多的写法最后不得不弃疗了,然后第二 ...

  3. Comet OJ 2019 夏季欢乐赛题解

    Comet OJ 2019 夏季欢乐赛题解 我是来骗访问量的 A 完全k叉树 \(n\)个点的完全k叉树的直径. 直接做 B 距离产生美 直接做 C 烤面包片 \(n!!!\mod p\) 显然\(n ...

  4. 2019.11.12&13题解

    写在前面: 虽然拿到了rk1,但是T3被卡常TLE90分,(考后再交就A了!?),lemon80,又丢失了一次良好的AK机会, 掐头去尾距离联赛仅剩2天,最近中午一直睡不好,可能是有些紧张, 希望自己 ...

  5. 【NOI 2019】同步赛 / 题解 / 感想

    非常颓写不动题怎么办…… 写下这篇博客警示自己吧…… 游记 7.16 我并不在广二参加 NOI,而是在距离广二体育馆一公里远的包间打同步赛(其实就是给写不动题找个理由) 上午身体不舒服,鸽了半天才看题 ...

  6. 2019.10.21 csp-s模拟测试81 反思总结

    T1: 把每一行状压,按行DP.设fi,j,k,i表示第几行,j是当前行的1覆盖状态,k是当前行选择按钮的状态.转移的时候枚举j和k,再枚举下一层的按钮选择情况l.如果l和j可以全覆盖当前层则转移合法 ...

  7. LeetCoded第21题题解--合并两个有序链表

    21. 合并两个有序链表 将两个升序链表合并为一个新的 升序 链表并返回.新链表是通过拼接给定的两个链表的所有节点组成的. 示例: 输入:1->2->4, 1->3->4 输出 ...

  8. [hgoi#2019/3/21]NOIP&NOI赛后总结

    前言 今天做的是是2010年提高组和NOI的题目,做过几道原题,但是还是爆炸了,我真的太弱了. t1-乌龟棋 https://www.luogu.org/problemnew/show/P1541 这 ...

  9. NOIP2017普及组T2题解

    还是神奇的链接 上面依然是题目. 这道题依然很简单,比起2015年的普及组t2好像还是更水一些. 不过这道题能讲的比第一题多. 我们一起来看一下吧! 这一题,我们首先将书的编号全部读入,存在一个数组里 ...

随机推荐

  1. H5谷歌登录 webview错误

    接入谷歌登录 H5接入谷歌登录打包apk使用webview谷歌登录不上(谷歌不支持用户代理被归类为嵌入式用户代理(也称为网络视图),因此不允许向Google发出OAuth授权请求) 解决办法:替换ua ...

  2. 珠峰-webpack

    ##### webpack的优势.可以做哪里事情. ##### npx的运行原理  https://zhuanlan.zhihu.com/p/27840803 #### webpack的插件 html ...

  3. JVM垃圾回收——GC

    一.JVM内存分配与回收 下图为堆内存结构图(注意:元数据区(MetaData )实际上不属于堆): 1.对象优先在Eden区分配 大多数情况下,对象在新生代中Eden区分配.当Eden区没有足够空间 ...

  4. 如何避免FOUC,是如何产生的

    FOUC(Flash Of Unstyled Content)即浏览器样式闪烁或者叫做无样式内存闪烁(用户定义样式表加载之前浏览器使用默认样式显示文档,用户样式加载渲染之后再从新显示文档,造成页面闪烁 ...

  5. linux 内核模块开发相关的文章搜集和模块开发过程中的小技巧

    最近需要开发一些内核模块,进行探究linux内核的一些特征,现在把一些遇到的比较好的文章和知识点,进行简要记录和备忘: 内核模块开发相关链接: https://www.thegeekstuff.com ...

  6. 回炉重造之重读Windows核心编程-002-字符集

    使用Unicode的优势: 便于在不同语言之间进行数据交换. 让你的exe或者dll文件支持所有的语言. 提高应用程序的执行效率. Windows2000是使用Unicode重新开发的,核心部分都需要 ...

  7. winform重绘控件边框

    首先添加一个用户控件 对于重绘边框有三个需要考虑的东西 1:是否显示边框 2:边框颜色 3:边框宽度 所以定义三个私有变量 /// <summary>/// 是否显示边框/// </ ...

  8. 重新安装python后,原来在虚拟环境里的django项目启动报错:dyld: Library not loaded: @executable_path/../.Python Referenced from: /Users/mac/.virtualenvs/WYGBlog-env/bin/python Reason: image not found

    因为当你创建一个虚拟环境的时候,一些软链接创建到原来的python上. 当用Homebrew更新python后,原来软连接对应的python已经不存在了. 因此需要把软链接指向新的python. 解决 ...

  9. vue实现打印功能

    通过npm 安装插件 1.安装  npm install vue-print-nb --save 2.引入  安装好以后在main.js文件中引入 import Print from 'vue-pri ...

  10. springBoot 中 logback配置文件详解

    logback介绍和配置详解 logback是Java的开源框架,性能比log4j要好.是springboot自带的日志框架.该框架主要有3个模块: logback-core:核心代码块(不介绍) l ...