SP913 QTREE2 - Query on a tree II

嘟嘟嘟


LCA水题,第二问看一下\(x\)到\(lca\)的路径长度是否够\(k - 1\),不过的话就从\(y\)出发往上跳。

#include<cstdio>
#include<iostream>
#include<cmath>
#include<algorithm>
#include<cstring>
#include<cstdlib>
#include<cctype>
#include<vector>
#include<stack>
#include<queue>
using namespace std;
#define enter puts("")
#define space putchar(' ')
#define Mem(a, x) memset(a, x, sizeof(a))
#define In inline
typedef long long ll;
typedef double db;
const int INF = 0x3f3f3f3f;
const db eps = 1e-8;
const int maxn = 1e5 + 5;
const int N = 18;
inline ll read()
{
  ll ans = 0;
  char ch = getchar(), last = ' ';
  while(!isdigit(ch)) last = ch, ch = getchar();
  while(isdigit(ch)) ans = (ans << 1) + (ans << 3) + ch - '0', ch = getchar();
  if(last == '-') ans = -ans;
  return ans;
}
inline void write(ll x)
{
  if(x < 0) x = -x, putchar('-');
  if(x >= 10) write(x / 10);
  putchar(x % 10 + '0');
}

char s[10];
int n;
struct Edge
{
  int nxt, to, w;
}e[maxn << 1];
int head[maxn], ecnt = -1;
In void addEdge(int x, int y, int w)
{
  e[++ecnt] = (Edge){head[x], y, w};
  head[x] = ecnt;
}

int dep[maxn], fa[N + 2][maxn];
ll dis[maxn];
In void dfs(int now, int _f)
{
  for(int i = 1; i <= N; ++i) fa[i][now] = 0;
  for(int i = 1; (1 << i) <= dep[now]; ++i)
    fa[i][now] = fa[i - 1][fa[i - 1][now]];
  for(int i = head[now], v; ~i; i = e[i].nxt)
    {
      if((v = e[i].to) == _f) continue;
      dep[v] = dep[now] + 1;
      fa[0][v] = now;
      dis[v] = dis[now] + e[i].w;
      dfs(v, now);
    }
}

In int lca(int x, int y)
{
  if(dep[x] < dep[y]) swap(x, y);
  for(int i = N; i >= 0; --i)
    if(dep[x] - (1 << i) >= dep[y]) x = fa[i][x];
  if(x == y) return x;
  for(int i = N; i >= 0; --i)
    if(fa[i][x] ^ fa[i][y]) x = fa[i][x], y = fa[i][y];
  return fa[0][x];
}

In ll query(int x, int y)
{
  int z = lca(x, y);
  return dis[x] + dis[y] - (dis[z] << 1);
}
In ll solve(int x, int y, int k)
{
  int z = lca(x, y);
  if(dep[x] - dep[z] < k) k = dep[y] + dep[x] - (dep[z] << 1) - k, swap(x, y);
  for(int i = N; i >= 0; --i)
    if((1 << i) <= k) x = fa[i][x], k -= (1 << i);
  return x;
}

int main()
{
  int T = read();
  while(T--)
    {
      Mem(head, -1), ecnt = -1;
      n = read();
      for(int i = 1; i < n; ++i)
    {
      int x = read(), y = read(), w = read();
      addEdge(x, y, w), addEdge(y, x, w);
    }
      dfs(1, 0);
      scanf("%s", s);
      while(s[1] != 'O')
    {
      int x = read(), y = read();
      if(s[1] == 'I') write(query(x, y)), enter;
      else
        {
          int k = read();
          write(solve(x, y, k - 1)), enter;
        }
      scanf("%s", s);
    }
    }
  return 0;
}

原文地址:https://www.cnblogs.com/mrclr/p/10655723.html

时间: 2024-10-25 17:43:40

SP913 QTREE2 - Query on a tree II的相关文章

LCA SP913 QTREE2 - Query on a tree II

SP913 QTREE2 - Query on a tree II 给定一棵n个点的树,边具有边权.要求作以下操作: DIST a b 询问点a至点b路径上的边权之和 KTH a b k 询问点a至点b有向路径上的第k个点的编号 有多组测试数据,每组数据以DONE结尾. 裸的LCA. 在处理第二个操作时,我直接向上数跳了多少个. 顾z大佬说不能这么做,要求出跳到那个点的深度再去跳. 真的是这样,不过懒得想了,应该是+1-1的误差. balabala... code: #include <iost

SPOJ QTREE2 Query on a tree II

Query on a tree II Time Limit: 2000ms Memory Limit: 262144KB This problem will be judged on SPOJ. Original ID: QTREE264-bit integer IO format: %lld      Java class name: Main You are given a tree (an undirected acyclic connected graph) with N nodes,

【SPOJ QTREE2】QTREE2 - Query on a tree II(LCA)

You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. Each edge has an integer value assigned to it, representing its length. We will ask you to perfrom some instructions of the following form: D

SPOJ 913 QTREE系列- Query on a tree II (倍增LCA)

题目地址:QTREE2 - Query on a tree II LCA学了离线与在线转RMQ方法后就去做这道题,于是想了好长时间也没想到怎么做.看了题解都是用的倍增LCA..于是又去学了下倍增法求LCA,这才发现用倍增法做简直是水题...因为求路径的第k个点可以转化成求第k个父节点,然而倍增法的原理就是根据的父节点,于是这题就很容易解决了.. 求距离很好求.关键是求路径第k个点,显然这个点要么是u的第k个父节点,要么是v的第k个父节点,于是乎,先求一次LCA,判断是u还是v的,然后用倍增法找到

SPOJ 题目913QTREE2 - Query on a tree II(Link Cut Tree 查询路径第k个点)

QTREE2 - Query on a tree II no tags You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. Each edge has an integer value assigned to it, representing its length. We will ask you to perfrom some i

SPOJ-QTREE2 Query on a tree II(暴力+LCA)

题目大意:给出一棵树,3种操作 DIST u,v 询问u到v的距离 KTH k, u, v 询问u到v的路径上的第k大的边的权值 解题思路:刚开始以为会爆,结果发现不会 直接暴力存储u到v的路上的所有边,再进行排序,输出第k大的边即可 #include <cstdio> #include <cstring> #define N 10010 struct Edge{ int to, next, cost; }E[2*N]; int head[N], depth[2 * N], fir

SPOJ 913 Query on a tree II ( 树链剖分 + 倍增 )

题目链接~~> 做题感悟:感觉又充实了一些. 解题思路:树链剖分 + 倍增 开始看时,第一问还好,第二问就不知道怎么解了.其实这两问都可以用倍增法解决. 先解释一下我理解的倍增 :记录 u 结点的 第 2 ^ i 个祖先,然后求u 的第 k 个祖先的时候,就相当于用 2 ^ i 去组合 k ,不断向上,一直到达第 k 个节点,其实每次更新的时k 的二进制中为 1 的位置.如下图,计算 u 的第 5 个祖先结点(这里不包括 u),先到达 u' 节点,然后再从 u' ,到 u'' (5 的二进制 1

SPOJ913 Query on a tree II

Time Limit: 433MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu Description You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. Each edge has an integer value assigned to it, represe

Query on a tree II 倍增LCA

You are given a tree (an undirected acyclic connected graph) with N nodes, and edges numbered 1, 2, 3...N-1. Each edge has an integer value assigned to it, representing its length. We will ask you to perfrom some instructions of the following form: D