[Luogu P3950] tribal conflicts

Problem

Description

Given a tree.

You need to address the following three things, all events are presented in chronological order.

  1. \ (Q, u, v \ ) representative asked \ (u, v \) can reach each other

  2. \ (C, u, v \ ) Representative \ (u, v \) between the OFF edge

  3. \ (U, x \) represents the \ (the U-\) times \ (C \) operation is restored

Input Format

The first line of the two numbers \ (n \) and \ (m \) , \ (n \) represents a total of \ (n \) tribes, \ (m \) represents the total of these three events

The next \ (n - 1 \) lines of two numbers \ (P, Q \) , represents the first \ (P \) points to the first \ (Q \) there is connected a road between points

The next \ (m \) rows, each row represents an operation, detailed description of the subject.

Output Format

For each \ (Q \) operations are given in a row Yesor Noon behalf result of the inquiry.

Range

\ (N, m \ 3 * 10 ^ 5 \)

Algorithm

Fenwick tree

Mentality

In fact, I wanted to practice hand look \ (LCT \) , but this problem by \ (LCT \) it seems overkill ......

Looked at roughly solution to a problem, with all the trees and cross \ (LCT \) like this, but in fact there is a very simple way, just Fenwick tree + random number.

The subject, for a path \ (u, v \) , this path Unicom iff \ (u, v \) sides have not been turned off on.

So how can we satisfy this condition is it? Replaced by requirements for off side, that is, for all current off the edge, \ (U, v \) or are within its sub-tree, or none at.

Then we can consider \ (dfn \) sequence + Fenwick tree maintenance sub-tree information, whenever each side of the break, Ode to each point within a sub-tree-specific information, and then when asked for \ ( u, v \) query the information above is equal to.

Fu special information on how to do this? Very simple, for each side are broken \ (rand \) a specific weight, all nodes in a tree within the sub-array to add this tree are the right values.

When the query need only check two things are the same weight on the line.

Reduction of time and then deleted just fine.

Code

#include <cstdio>
#include <cstdlib>
#include <ctime>
#include <iostream>
using namespace std;
#define LL long long
#define go(G, x, i, v) \
  for (int i = G.hd[x], v = G.to[i]; i; v = G.to[i = G.nx[i]])
#define inline __inline__ __attribute__((always_inline))
inline LL read() {
  LL x = 0, w = 1;
  char ch = getchar();
  while (!isdigit(ch)) {
    if (ch == '-') w = -1;
    ch = getchar();
  }
  while (isdigit(ch)) {
    x = (x << 3) + (x << 1) + ch - '0';
    ch = getchar();
  }
  return x * w;
}

const int Max_n = 3e5 + 5, mod = 998244353;
int n, m;
int cntd, dep[Max_n], dfn[Max_n], siz[Max_n];
int c[Max_n];
struct graph {
  int hd[Max_n];
  int cntr, nx[Max_n << 1], to[Max_n << 1];
  void addr(int u, int v) {
    cntr++;
    nx[cntr] = hd[u], to[cntr] = v;
    hd[u] = cntr;
  }
} G;
struct que {
  int u, v, x;
} k[Max_n];

namespace Input {
void main() {
  n = read(), m = read();
  int u, v;
  for (int i = 1; i < n; i++) {
    u = read(), v = read();
    G.addr(u, v), G.addr(v, u);
  }
}
}  // namespace Input

namespace Init {
void build(int x, int fa) {
  dep[x] = dep[fa] + 1, siz[x] = 1, dfn[x] = ++cntd;
  go(G, x, i, v) if (v != fa) build(v, x), siz[x] += siz[v];
}
void main() { build(1, 0); }
}  // namespace Init

namespace Solve {
void add(int k, int x) {
  for (int i = k; i <= n; i += i & -i) (c[i] += x) %= mod;
}
int query(int k) {
  int ans = 0;
  for (int i = k; i; i -= i & -i) (ans += c[i]) %= mod;
  return (ans + mod) % mod;
}
void main() {
  srand((unsigned)time(NULL));
  int cnt = 0, u, v;
  char op;
  for (int i = 1; i <= m; i++) {
    scanf(" %c", &op);
    u = read();
    if (op == 'U')
      add(dfn[k[u].v], -k[u].x), add(dfn[k[u].v] + siz[k[u].v], k[u].x);
    else {
      v = read();
      if (op == 'Q')
        printf("%s\n", query(dfn[u]) == query(dfn[v]) ? "Yes" : "No");
      else {
        k[++cnt].x = rand() % mod;
        if (dep[u] > dep[v]) swap(u, v);
        add(dfn[v], k[cnt].x), add(dfn[v] + siz[v], -k[cnt].x);
        k[cnt].u = u, k[cnt].v = v;
      }
    }
  }
}
}  // namespace Solve

int main() {
#ifndef ONLINE_JUDGE
  freopen("3950.in", "r", stdin);
  freopen("3950.out", "w", stdout);
#endif
  Input::main();
  Init::main();
  Solve::main();
}

Guess you like

Origin www.cnblogs.com/luoshuitianyi/p/12147126.html