This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
//
// Created by 42kangaroo on 07/02/2024.
//
#include "bits/stdc++.h"
using namespace std;
template<typename T>
using g_t = vector<vector<T>>;
struct Que {
char c;
int f, s;
string an;
};
struct BinL {
bool asc, desc;
int p, upVal, downVal;
};
struct Ed {
int a, b, w;
};
struct FenT {
vector<int> a, cooC;
void inc(int k, int v) {
int p = std::lower_bound(cooC.begin(), cooC.end(), k) - cooC.begin();
for (int i = p + 1; i < a.size(); i += i & -i) {
a[i] += v;
}
}
int get(int k) {
int res = 0;
if (k < 0) return 0;
int p = std::lower_bound(cooC.begin(), cooC.end(), k) - cooC.begin();
for (int i = p + 1; i > 0; i -= i & -i) {
res += a[i];
}
return res;
}
};
array<int, 120005> logT;
g_t<BinL> binL;
g_t<Ed> g;
vector<int> de;
vector<int> pCD;
vector<int> dCD;
vector<FenT> fCD;
void dfs(int n, int p, int d, vector<pair<int, int>> &pa) {
pa[n].first = p;
de[n] = d;
for (auto &e: g[n]) {
if (e.b == p) {
pa[n].second = e.w;
continue;
}
dfs(e.b, n, d + 1, pa);
}
}
BinL combine(const BinL &l, const BinL &r) {
BinL res{};
res.p = r.p;
res.upVal = r.upVal;
res.downVal = l.downVal;
res.asc = l.asc && r.asc && l.upVal > r.downVal;
res.desc = l.desc && r.desc && l.upVal < r.downVal;
return res;
}
BinL reverse(const BinL& in) {
BinL res{};
res.p = -1;
res.upVal = in.downVal;
res.downVal = in.upVal;
res.asc = in.desc;
res.desc = in.asc;
return res;
}
void binLPrep(vector<pair<int, int>> &p) {
binL = g_t<BinL>(logT[p.size()] + 1, vector<BinL>(p.size()));
for (int i = 0; i < p.size(); ++i) {
binL[0][i] = {true, true, p[i].first, p[i].second, p[i].second};
}
for (int i = 1; i < binL.size(); ++i) {
for (int j = 0; j < p.size(); ++j) {
binL[i][j] = combine(binL[i - 1][j], binL[i - 1][binL[i - 1][j].p]);
}
}
}
pair<bool, BinL> connected(int i, int st, int en) {
if (st == en) return {true, {true, true, -1, -1, -1}};
bool sw = false;
if (de[st] < de[en]) {
sw = true;
swap(st, en);
}
int k = de[st] - de[en];
BinL biSt{true, true, -1, -1, -1};
BinL biEn{true, true, -1, -1, -1};
for (int j = 0; k; k >>= 1, ++j) {
if (k & 1) {
if (biSt.p == -1) {
biSt = binL[j][st];
} else {
biSt = combine(biSt, binL[j][st]);
}
st = biSt.p;
}
}
if (st == en) {
if (sw) {
return {biSt.asc && biSt.downVal <= i, reverse(biSt)};
} else {
return {biSt.desc && biSt.upVal <= i, biSt};
}
}
for (int j = binL.size() - 1; j >= 0; j--) {
if (binL[j][st].p != binL[j][en].p) {
if (biSt.p == -1) {
biSt = binL[j][st];
} else {
biSt = combine(biSt, binL[j][st]);
}
st = biSt.p;
if (biEn.p == -1) {
biEn = binL[j][en];
} else {
biEn = combine(biEn, binL[j][en]);
}
en = biEn.p;
}
}
if (biSt.p == -1) {
biSt = binL[0][st];
} else {
biSt = combine(biSt, binL[0][st]);
}
if (biEn.p == -1) {
biEn = binL[0][en];
} else {
biEn = combine(biEn, binL[0][en]);
}
if (sw) {
swap(biEn, biSt);
}
auto reVbiEn = reverse(biEn);
return {biSt.desc && biEn.asc && biSt.upVal < biEn.upVal && biEn.downVal <= i, combine(biSt, reVbiEn)};
}
int dfsSi(int n, int p, vector<bool> &vis, vector<int> &si) {
if (vis[n]) return 0;
si[n] = 1;
for (auto &e: g[n]) {
if (e.b == p) continue;
si[n] += dfsSi(e.b, n, vis, si);
}
return si[n];
}
int dfsCentro(int n, int p, int to, vector<bool> &vis, vector<int> &si) {
for (auto &e: g[n]) {
if (vis[e.b] || e.b == p) continue;
if (2 * si[e.b] >= to) return dfsCentro(e.b, n, to, vis, si);
}
return n;
}
void CenTroDecomp(int n, int p, int d, vector<bool> &vis, vector<int> &si) {
dfsSi(n, n, vis, si);
int c = dfsCentro(n, n, si[n], vis, si);
if (p == -1) p = c;
pCD[c] = p;
vis[c] = true;
dCD[c] = d;
for (auto &e: g[c]) {
if (!vis[e.b]) {
fCD[c].cooC.push_back(e.w);
CenTroDecomp(e.b, c, d + 1, vis, si);
}
}
std::sort(fCD[c].cooC.begin(), fCD[c].cooC.end());
fCD[c].a.resize(fCD[c].cooC.size() + 2, 0);
}
void updCD(Ed e) {
Ed oE = e;
if (dCD[e.a] < dCD[e.b]) swap(e.a, e.b);
while (dCD[e.a] != dCD[e.b]) {
e.a = pCD[e.a];
}
while (e.a != e.b) {
e.a = pCD[e.a];
e.b = pCD[e.b];
}
for (;;) {
auto [con, bi] = connected(e.w - 1, e.a, oE.a);
if (con) {
auto re = connected(e.w, e.a, oE.b);
con = re.first;
bi = re.second;
} else {
auto re = connected(e.w, e.a, oE.a);
con = re.first;
bi = re.second;
}
if (con) fCD[e.a].inc(bi.downVal, 1);
if (pCD[e.a] == e.a) break;
e.a = pCD[e.a];
}
}
int numWith(int c, int i) {
int res = 0;
int oC = c;
for (;;) {
auto [con, bi] = connected(i, oC, c);
if (con) {
res += fCD[c].get(1e6) - fCD[c].get(bi.upVal) + 1;
}
if (pCD[c] == c) break;
c = pCD[c];
}
return res;
}
signed main() {
ios_base::sync_with_stdio(false);
cin.tie(nullptr);
int n, k;
cin >> n >> k;
logT[1] = 0;
for (int i = 2; i < logT.size(); ++i) {
logT[i] = logT[i / 2] + 1;
}
g = g_t<Ed>(n);
vector<Que> que(k + n - 1);
for (int i = 0; i < k + n - 1; ++i) {
char c;
cin >> c;
if (c == 'S') {
int a, b;
cin >> a >> b;
--a;
--b;
g[a].push_back({a, b, i});
g[b].push_back({b, a, i});
que[i] = {c, a, b, ""};
}
if (c == 'Q') {
int a, b;
cin >> a >> b;
--a;
--b;
que[i] = {c, a, b, ""};
}
if (c == 'C') {
int a;
cin >> a;
--a;
que[i] = {c, a, -1, ""};
}
}
vector<pair<int, int>> p(n, {0, 0});
de = vector<int>(n);
dfs(0, 0, 0, p);
binLPrep(p);
vector<bool> vis(n, false);
vector<int> si(n, 0);
pCD.resize(n);
dCD.resize(n);
fCD.resize(n);
CenTroDecomp(0, -1, 0, vis, si);
for (int i = 0; i < que.size(); ++i) {
if (que[i].c == 'S') {
updCD({que[i].f, que[i].s, i});
}
if (que[i].c == 'Q') {
que[i].an = (connected(i, que[i].s, que[i].f).first ? "yes" : "no");
}
if (que[i].c == 'C') {
que[i].an = to_string(numWith(que[i].f, i));
}
}
for (auto &qu: que) {
if (!qu.an.empty()) cout << qu.an << "\n";
}
}
Compilation message (stderr)
servers.cpp: In member function 'void FenT::inc(int, int)':
servers.cpp:31:25: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<int>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
31 | for (int i = p + 1; i < a.size(); i += i & -i) {
| ~~^~~~~~~~~~
servers.cpp: In function 'void binLPrep(std::vector<std::pair<int, int> >&)':
servers.cpp:90:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
90 | for (int i = 0; i < p.size(); ++i) {
| ~~^~~~~~~~~~
servers.cpp:93:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::vector<BinL, std::allocator<BinL> >, std::allocator<std::vector<BinL, std::allocator<BinL> > > >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
93 | for (int i = 1; i < binL.size(); ++i) {
| ~~^~~~~~~~~~~~~
servers.cpp:94:21: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<std::pair<int, int> >::size_type' {aka 'long unsigned int'} [-Wsign-compare]
94 | for (int j = 0; j < p.size(); ++j) {
| ~~^~~~~~~~~~
servers.cpp: In function 'int main()':
servers.cpp:243:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::array<int, 120005>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
243 | for (int i = 2; i < logT.size(); ++i) {
| ~~^~~~~~~~~~~~~
servers.cpp:284:20: warning: comparison of integer expressions of different signedness: 'int' and 'std::vector<Que>::size_type' {aka 'long unsigned int'} [-Wsign-compare]
284 | for (int i = 0; i < que.size(); ++i) {
| ~~^~~~~~~~~~~~
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |