제출 #850572

#제출 시각아이디문제언어결과실행 시간메모리
850572tvladm2009Inside information (BOI21_servers)C++17
100 / 100
561 ms140100 KiB
#include <bits/stdc++.h>

using namespace std;

const int N = 480000 + 777;
const int K = 20;
int n;
int k;
vector<pair<int, int>> g[N];
int tab[K][N];
int maxEdge[K][N];
bool inc[K][N];
bool desc[K][N];
int weight[N];
int dep[N];
vector<int> qs[N];
bool active[N];
int sz[N];
int aib[N];

struct T {
  char type;
  int a;
  int b;
  int d;
  int id;
};

vector<T> events;
int sol[2 * N];

int get(int a, int x) {
  for (int k = K - 1; k >= 0; k--) {
    if (x & (1 << k)) {
      a = tab[k][a];
    }
  }
  return a;
}

void build(int a, int p = 0) {
  tab[0][a] = p;
  maxEdge[0][a] = weight[a];
  for (int k = 1; k < K; k++) {
    tab[k][a] = tab[k - 1][tab[k - 1][a]];
    maxEdge[k][a] = max(maxEdge[k - 1][a], maxEdge[k - 1][tab[k - 1][a]]);
  }
  inc[0][a] = 1;
  inc[1][a] = (weight[a] < weight[p]);
  for (int k = 2; k < K; k++) {
    if (inc[k - 1][a] && inc[k - 1][tab[k - 1][a]] && weight[get(a, (1 << (k - 1)) - 1)] < weight[get(a, (1 << (k - 1)))] && weight[get(a, (1 << (k - 1)))] < weight[get(a, (1 << (k - 1)) + 1)]) {
      inc[k][a] = 1;
    }
  }
  desc[0][a] = 1;
  desc[1][a] = (weight[a] > weight[p]);
  for (int k = 2; k < K; k++) {
    if (desc[k - 1][a] && desc[k - 1][tab[k - 1][a]] && weight[get(a, (1 << (k - 1)) - 1)] > weight[get(a, (1 << (k - 1)))] && weight[get(a, (1 << (k - 1)))] > weight[get(a, (1 << (k - 1)) + 1)]) {
      desc[k][a] = 1;
    }
  }
  for (auto &b : g[a]) {
    if (b.first == p) continue;
    dep[b.first] = dep[a] + 1;
    weight[b.first] = b.second;
    build(b.first, a);
  }
}

int get_lca(int x, int y) {
  if (dep[x] < dep[y]) {
    swap(x, y);
  }
  for (int k = K - 1; k >= 0; k--) {
    if (dep[x] - (1 << k) >= dep[y]) {
      x = tab[k][x];
    }
  }
  if (x == y) {
    return x;
  }
  for (int k = K - 1; k >= 0; k--) {
    if (tab[k][x] != tab[k][y]) {
      x = tab[k][x];
      y = tab[k][y];
    }
  }
  return tab[0][x];
}

int under(int x, int y) { /// y is ancestor of x
  return get(x, dep[x] - dep[y] - 1);
}

bool isInc(int x, int y) { /// y is ancestor of x
  bool ok = 1;
  int xinit = x;
  for (int k = K - 1; k >= 0; k--) {
    if (dep[x] - (1 << k) >= dep[y]) {
      ok &= inc[k][x];
      x = tab[k][x];
      if (x == y) {
        break;
      }
      ok &= (weight[x] > weight[get(xinit, dep[xinit] - dep[x] - 1)]);
    }
  }
  return ok;
}

bool isDesc(int x, int y) { /// y is ancestor of x
  bool ok = 1;
  int xinit = x;
  for (int k = K - 1; k >= 0; k--) {
    if (dep[x] - (1 << k) >= dep[y]) {
      ok &= desc[k][x];
      x = tab[k][x];
      if (x == y) {
        break;
      }
      ok &= (weight[x] < weight[get(xinit, dep[xinit] - dep[x] - 1)]);
    }
  }
  return ok;
}

int get_max(int x, int y) {
  int z = get_lca(x, y);
  int ret = 0;
  for (int k = K - 1; k >= 0; k--) {
    if (dep[x] - (1 << k) >= dep[z]) {
      ret = max(ret, maxEdge[k][x]);
      x = tab[k][x];
    }
  }
  for (int k = K - 1; k >= 0; k--) {
    if (dep[y] - (1 << k) >= dep[z]) {
      ret = max(ret, maxEdge[k][y]);
      y = tab[k][y];
    }
  }
  return ret;
}

bool cmp(pair<int, int> a, pair<int, int> b) {
  return a.second > b.second;
}

void get_sizes(int a, int p = 0) {
  sz[a] = 1;
  for (auto &b : g[a]) {
    if (b.first == p) {
      continue;
    }
    if (active[b.first] == 0) {
      get_sizes(b.first, a);
      sz[a] += sz[b.first];
    }
  }
}

int get_centroid(int a, int limit, int p = 0) {
  for (auto &b : g[a]) {
    if (b.first == p) {
      continue;
    }
    if (active[b.first] == 0 && sz[b.first] >= limit) {
      return get_centroid(b.first, limit, a);
    }
  }
  return a;
}

void add(int i, int x) {
  while (i < N) {
    aib[i] += x;
    i += i & -i;
  }
}

int get(int i) {
  int ret = 0;
  while (i) {
    ret += aib[i];
    i -= i & -i;
  }
  return ret;
}

vector<int> good;

void percolate(int a, int p, int last, int first, bool inc, bool dec) {
  if (dec == true) {
    for (auto &i : qs[a]) {
      sol[i] += get(i);
      if (first <= i) {
        sol[i]++;
      }
    }
  }
  if (inc == true) {
    good.push_back(last);
  }
  for (auto &b : g[a]) {
    if (b.first == p) {
      continue;
    }
    if (!active[b.first]) {
      bool inc2 = inc, dec2 = dec;
      if (b.second < last) {
        inc2 = 0;
      }
      if (b.second > last) {
        dec2 = 0;
      }
      percolate(b.first, a, b.second, first, inc2, dec2);
    }
  }
}

void decompose(int a, int p = 0) {
  get_sizes(a, a);
  a = get_centroid(a, (sz[a] + 1) / 2, a);
  active[a] = true;
  vector<int> not_active_kids;
  for (auto &b : g[a]) {
    if (!active[b.first]) {
      percolate(b.first, a, b.second, b.second, 1, 1);
      for (auto &i : good) {
        add(i, 1);
        not_active_kids.push_back(i);
      }
      good.clear();
    }
  }
  for (auto &i : qs[a]) {
    sol[i] += get(i);
  }
  for (auto &i : not_active_kids) {
    add(i, -1);
  }
  for (auto &b : g[a]) {
    if (b.first == p) {
      continue;
    }
    if (!active[b.first]) {
      decompose(b.first, a);
    }
  }
}

int main() {
  ios::sync_with_stdio(0); cin.tie(0); cout.tie(0);

  // freopen ("input", "r", stdin);

  cin >> n >> k;
  for (int i = 1; i <= n + k - 1; i++) {
    T aux;
    cin >> aux.type;
    if (aux.type == 'S') {
      cin >> aux.a >> aux.b;
    } else if (aux.type == 'Q') {
      cin >> aux.a >> aux.d;
    } else if (aux.type == 'C') {
      cin >> aux.d;
    }
    aux.id = i;
    events.push_back(aux);
  }
  for (auto &e : events) {
    if (e.type == 'S') {
      g[e.a].push_back({e.b, e.id});
      g[e.b].push_back({e.a, e.id});
    }
  }
  dep[1] = 1;
  build(1);

  for (auto &e : events) {
    if (e.type == 'S' || e.type == 'C') {
      continue;
    }

    int x = e.a;
    int y = e.d;
    int z = get_lca(x, y);
    int mx = get_max(x, y);
    if (mx > e.id) {
      continue;
    }
    if (z == x) {
      sol[e.id] = isInc(y, x);
      continue;
    }
    if (z == y) {
      sol[e.id] = isDesc(x, y);
      continue;
    }
    if (isInc(y, z) && isDesc(x, z) && weight[under(y, z)] < weight[under(x, z)]) {
      sol[e.id] = 1;
    } else {
      sol[e.id] = 0;
    }
  }

  for (int i = 0; i < n + k - 1; i++) {
    if (events[i].type == 'C') {
      qs[events[i].d].push_back(events[i].id);
    }
  }
  for (int i = 1; i <= n; i++) {
    sort(g[i].begin(), g[i].end(), cmp);
  }
  decompose(1);

  for (auto &e : events) {
    if (e.type == 'Q') {
      cout << (sol[e.id] == 1 ? "yes" : "no") << "\n";
    } else if (e.type == 'C') {
      cout << sol[e.id] + 1 << "\n";
    }
  }
  return 0;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...