代码求条
查看原帖
代码求条
998707
spire001楼主2025/1/26 07:54
#include <algorithm>
#include <cassert>
#include <cstring>
#include <iostream>
#include <numeric>
#include <stack>
#include <vector>

#define lowbit(x) (x & -(x))

using namespace std;

typedef long long LL;
constexpr int mod = 998244353;
constexpr int N = 500010, M = 20;
template <typename Tp1, typename Tp2> inline void cmax(Tp1 &A, const Tp2 &B)
{
  if (A < B)
    A = B;
  return;
}
template <typename Tp1, typename Tp2> inline void cmin(Tp1 &A, const Tp2 &B)
{
  if (A > B)
    A = B;
  return;
}
template <typename Tp1, typename Tp2, int mod = ::mod>
inline void ad(Tp1 &A, const Tp2 &B)
{
  A = (A + B) % mod;
  return;
}
template <typename Tp1, typename Tp2, int mod = ::mod>
inline void sb(Tp1 &A, const Tp2 &B)
{
  A = (A + mod - B) % mod;
  return;
}
int ans[N], n, a[N], st[M][N], dep[N], son[N], top[N], k, c[N << 1], fa[N],
    siz[N], lg[N];
int L[N], R[N], K[N], stl[N], str[N];
inline void add(const int x, const int val)
{
  for (int i = x; i <= k; i += lowbit(i))
    cmax(c[i], val);
  return;
}
inline void clear(const int x)
{
  for (int i = x; i <= k; i += lowbit(i))
    c[i] = 0;
  return;
}
inline int ask(const int x)
{
  int res = 0;
  for (int i = x; i; i &= i - 1)
    cmax(res, c[i]);
  return res;
}
struct node
{
  int next, to;
} e[N << 1];
int head[N], es;
void bian(int u, int v)
{
  e[++es] = {head[u], v};
  head[u] = es;
  return;
}

struct cdq_t
{
  int a, b, c;
  int id, tp;
  explicit cdq_t(int _a, int _b, int _c, int _id, int _tp)
      : a(_a), b(_b), c(_c), id(_id), tp(_tp)
  {
    assert(c >= 0 && c <= n);
  }
  bool operator<(cdq_t A) const
  {
    if (a != A.a)
      return a < A.a;
    if (b != A.b)
      return b < A.b;
    return id > A.id;
  }
  // auto& operator=(const cdq_t &A) 
  // {
  //   a = A.a; b = A.b; c = A.c;
  //   id = A.id; tp = A.tp;
  //   // abort();
  //   return *this;
  // }
  cdq_t() = default;
  int &val() const { return ans[id]; }
} q[N], cpy[N];

void pre()
{
  for (int i = 2; i != N; i++)
    lg[i] = lg[i >> 1] + 1;
  return;
}
void dfs1(int u)
{
  siz[u] = 1;
  for (int i = head[u]; i; i = e[i].next)
    if (const int v = e[i].to; v != fa[u])
    {
      fa[v] = u;
      dep[v] = dep[u] + 1;
      dfs1(v);
      siz[u] += siz[v];
      if (siz[v] > siz[son[u]])
        son[u] = v;
    }
  return;
}
void dfs2(int u, int tp)
{
  top[u] = tp;
  if (son[u])
    dfs2(son[u], tp);

  for (int i = head[u]; i; i = e[i].next)
    if (const int v = e[i].to; v != fa[u] && v != son[u])
      dfs2(v, v);

  return;
}
int get(int l, int r)
{
  int tmp = lg[r - l + 1];
  return max(st[tmp][l], st[tmp][r - (1 << tmp) + 1]);
}
void cdq(int l, int r)
{
  // for (int i = l; i <= r; i++)
  //   for (int j = l; j <= r; j++)
  //     if (q[i].tp == 1 && q[j].tp == 0 && q[i].a <= q[j].a &&
  //         q[i].b <= q[j].b && q[i].c <= q[j].c)
  //       cmax(q[j].val(), a[q[i].id]);
  // return;
  // 这里的注释是暴力,加上这部分代码就是对的
  if (l == r)
    return;

  const int mid = (l + r) >> 1;
  cdq(l, mid);
  cdq(mid + 1, r);

  int i = l, j = mid + 1, tot = l;

  while (i <= mid && j <= r)
  {
    if (q[i].b < q[j].b || (q[i].b == q[j].b && q[i].tp == 1))
    {
      if (q[i].tp == 1) // 0 = ask 1 = point
        add(q[i].c, a[q[i].id]);
      cpy[tot++] = q[i++];
    }
    else
    {
      if (q[j].tp == 0)
        cmax(q[j].val(), ask(q[j].c));
      cpy[tot++] = q[j++];
    }
  }

  while (j <= r)
  {
    if (q[j].tp == 0)
      cmax(q[j].val(), ask(q[j].c));
    cpy[tot++] = q[j++];
  }
  for (int p = l; p != i; p++)
    if (q[p].tp == 1)
      clear(q[p].c);
  while (i <= mid)
  {
    // if (q[i].tp == 0) // 0 = ask 1 = point
    //   cmax(q[i].val(), ask(q[i].c));
    cpy[tot++] = q[i++];
  }

  // copy(cpy + l, cpy + tot, q + l);
  // assert(tot = r + 1);
  for (int p = l; p <= r; p++) q[p] = cpy[p];
  // for (int p = l; p <= r; p++) cerr << q[p].b << ' ';
  // cerr << endl;
}
int main()
{
  ios::sync_with_stdio(false);
  cin.tie(nullptr);
  cout.tie(nullptr);

//   freopen("query2.in", "r", stdin);
//   freopen("out.txt", "w", stdout);

  pre();

  cin >> n;

  for (int i = 1; i != n; i++)
  {
    int u, v;
    cin >> u >> v;
    bian(u, v);
    bian(v, u);
  }

  dfs1(dep[1] = 1);
  dfs2(1, 1);

  auto LCA = [](int x, int y)
  {
    while (top[x] != top[y])
      dep[top[x]] >= dep[top[y]] ? x = fa[top[x]] : y = fa[top[y]];
    return dep[x] <= dep[y] ? x : y;
  };
  for (int i = 1; i <= n; i++)
  {
    a[i] = dep[LCA(i, i + 1)];
    st[0][i] = dep[i];
  }
  // for (int i = 1; i <= n; i++) cout << a[i] << ' ';
  for (int i = 1; (1 << i) <= n; i++)
    for (int j = 1; j + (1 << i) <= n + 1; j++)
      st[i][j] = max(st[i - 1][j], st[i - 1][j + (1 << (i - 1))]);

  int T;
  cin >> T;

  for (int i = 1; i <= T; i++)
  {
    cin >> L[i] >> R[i] >> K[i];
    if (--K[i] == 0)
      ans[i] = get(L[i], R[i]);
    R[i]--;
  }

  int cnt = 0;

  stack<int> stk;
  for (int i = 1; i < n; i++)
    stl[i] = str[i] = i;

  for (int i = 1; i < n; i++)
  {
    while (!stk.empty() && a[stk.top()] > a[i])
    {
      str[stk.top()] = i - 1;
      stk.pop();
    }
    stk.push(i);
  }
  while (stk.size())
    str[stk.top()] = n - 1, stk.pop();
  for (int i = n - 1; i >= 1; i--)
  {
    while (!stk.empty() && a[stk.top()] > a[i])
    {
      stl[stk.top()] = i + 1;
      stk.pop();
    }
    stk.push(i);
  }
  while (stk.size())
    stl[stk.top()] = 1, stk.pop();

  k = n + 1;

  for (int i = 1; i <= T; i++)
    if (K[i])
    {
      /*
      R[i] <= str[j]
      R[i] - K[i] + 1 >= stl[j]
      L[i] <= stl[j]
      */
      q[++cnt] = cdq_t(n - R[i], n - (K[i] - R[i] - 1), n - L[i], i, 0);
    }
  for (int i = 1; i < n; i++)
    q[++cnt] = cdq_t(n - str[i], n + stl[i], n - stl[i], i, 1);
  sort(q + 1, q + cnt + 1);
  cdq(1, cnt);
  cnt = 0;
  for (int i = 1; i <= T; i++)
    if (K[i])
    {
      /*
      R[i] <= str[j]
      L[i] >= stl[j]
      R[i] - L[i] + 1 - K[i] >= 0
      */
      q[++cnt] = cdq_t(n - R[i], n + L[i], 1, i, 0);
    }
  for (int i = 1; i < n; i++)
    q[++cnt] = cdq_t(n - str[i], n + stl[i], 1, i, 1);
  sort(q + 1, q + cnt + 1);
  cdq(1, cnt);
  cnt = 0;
  for (int i = 1; i <= T; i++)
    if (K[i])
    {
      /*
      R[i] >= str[j]
      K[i] - 1 <= str[j] - stl[j]
      L[i] <= stl[j]
       */
      q[++cnt] = cdq_t(n + R[i], n - K[i] + 1, n - L[i], i, 0);
    }
  for (int i = 1; i < n; i++)
    q[++cnt] = cdq_t(n + str[i], n - str[i] + stl[i], n - stl[i], i, 1);
  sort(q + 1, q + cnt + 1);
  cdq(1, cnt);
  cnt = 0;
  for (int i = 1; i <= T; i++)
    if (K[i])
    {
      /*
      R[i] >= str[j]
      L[i] + K[i] <= str[i] + 1
      L[i] >= stl[j]
       */
      q[++cnt] = cdq_t(n + R[i], n - L[i] - K[i], L[i], i, 0);
    }
  for (int i = 1; i < n; i++)
    q[++cnt] = cdq_t(n + str[i], n - str[i] - 1, stl[i], i, 1);
  sort(q + 1, q + cnt + 1);
  cdq(1, cnt);
  cnt = 0;

  for (int i = 1; i <= T; i++)
    cout << ans[i] << '\n';

  return 0;
}

思路是利用 depLCAi=LRi=mindepLCA(i,i+1)dep_{\operatorname{LCA}_{i=L}^R i}=\min dep_{LCA(i, i+1)},求出数组 {W}\{W\},然后单调栈求出可能对于每个 iiWiW_i 是最小值的区间,然后用 cdq 分治 求出单调栈区间与询问区间交长度大于或等于 k1k-1 且值最大的点的贡献离线做本题。暴力可以过大样例,大概是 cdq 分治 写错了求条。

2025/1/26 07:54
加载中...