CF1304E 1-Trees and Queries
阿新 • • 發佈:2021-11-02
對樹的路徑進行操作,不難想到樹的路徑是唯一的,離不開LCA
新增一條新邊後,答案有兩種可能,一是走原樹上路徑,二是通過這條邊走到
對於後者,其實答案就是dis(a,x)+1+dis(y,b)或者dis(a,y)+1+dis(x,b)
均是樹上原有的,LCA可求
但是有個特殊情況,可以反覆橫跳(噁心心
但是反覆橫跳的奇偶性不變,只要有一個答案<=K並且和K奇偶性相同即可
#include <cstdio> #include <iostream> using namespace std; #define MAXN 100005 struct edge { int v,next; } G[MAXN<<1]; int head[MAXN],tot = 0; inline void add(int u,int v) { G[++tot].v = v; G[tot].next = head[u]; head[u] = tot; } struct Tree { int son[MAXN],size[MAXN],fa[MAXN],d[MAXN]; int top[MAXN]; void dfs1(int u,int father) { fa[u] = father; d[u] = d[father] + 1; size[u] = 1; son[u] = 0; for(int i=head[u];i;i=G[i].next) { int v = G[i].v; if(v==fa[u]) continue; dfs1(v,u); size[u] += size[v]; if(size[v]>size[son[u]]) son[u] = v; } } void dfs2(int u,int tp) { top[u] = tp; if(son[u]) dfs2(son[u],tp); for(int i=head[u];i;i=G[i].next) { int v = G[i].v; if(v==fa[u]||v==son[u]) continue; dfs2(v,v); } } inline void init() { d[1] = size[0] = 0; dfs1(1,1); dfs2(1,1); } inline int LCA(int u,int v) { while(top[u]!=top[v]) { if(d[top[u]]<d[top[v]]) swap(u,v); u = fa[top[u]]; } return d[u]>d[v]?v:u; } inline int dis(int u,int v) { int lca = LCA(u,v); return (d[u]-d[lca]) + (d[v]-d[lca]); } } tr; inline bool check(int dis1,int dis2) { return (dis1<=dis2&&(dis1&1)==(dis2&1)); } int N,Q; int main() { ios::sync_with_stdio(0); cin.tie(0); cout.tie(0); cin >> N; for(int i=1;i<N;++i) { int u,v; cin >> u >> v; add(u,v); add(v,u); } tr.init(); cin >> Q; for(int i=1;i<=Q;++i) { int x,y,a,b,k; cin >> x >> y >> a >> b >> k; if(check(tr.dis(a,b),k)||check(tr.dis(a,x)+1+tr.dis(y,b),k)||check(tr.dis(a,y)+1+tr.dis(x,b),k)) cout << "YES\n"; else cout << "NO\n"; } return 0; }