Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #ifdef DEBUG
- //#define _GLIBCXX_DEBUG
- #endif
- #include <bits/stdc++.h>
- using namespace std;
- typedef long double ld;
- #ifdef DEBUG
- #define eprintf(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
- #else
- #define eprintf(...) ;
- #endif
- #define sz(x) ((int) (x).size())
- #define TASK "text"
- const int inf = (int) 1.01e9;
- const long long infll = (long long) 1.01e18;
- const ld eps = 1e-9;
- const ld pi = acos((ld) -1);
- #ifdef DEBUG
- mt19937 mrand(300);
- #else
- mt19937 mrand(chrono::steady_clock::now().time_since_epoch().count());
- #endif
- int rnd(int x) {
- return mrand() % x;
- }
- void precalc() {
- }
- const int maxn = (int) 1e5 + 5;
- int n, q;
- bool read() {
- if (scanf("%d%d", &n, &q) < 2) {
- return false;
- }
- return true;
- }
- vector<int> g[maxn];
- int p[maxn], ppos[maxn];
- int ts[maxn], mxts[maxn];
- int dep[maxn];
- vector<int> gd[maxn];
- vector<vector<int>> ds[maxn];
- vector<int> allds[maxn];
- map<int, int> dist[maxn];
- void getVs(int v, int p, int d, int minDep, vector<pair<int, int>> &vs) {
- vs.push_back(make_pair(v, d));
- for (int i = 0; i < sz(g[v]); i++) {
- int u = g[v][i];
- if (u == p || dep[u] < minDep) {
- continue;
- }
- getVs(u, v, d + 1, minDep, vs);
- }
- }
- int s[maxn];
- void getS(int v, int p) {
- s[v] = 1;
- for (int i = 0; i < sz(g[v]); i++) {
- int u = g[v][i];
- if (u == p || dep[u] < inf) {
- continue;
- }
- getS(u, v);
- s[v] += s[u];
- }
- }
- int getCentroid(int v) {
- getS(v, -1);
- int alls = s[v];
- int pv = -1;
- while (true) {
- int nv = -1;
- for (int i = 0; i < sz(g[v]); i++) {
- int u = g[v][i];
- if (u == pv || dep[u] < inf) {
- continue;
- }
- if (2 * s[u] > alls) {
- nv = u;
- }
- }
- if (nv == -1) {
- break;
- }
- pv = v;
- v = nv;
- }
- return v;
- }
- int rebuild(int v, int curDep) {
- v = getCentroid(v);
- ts[v] = 1;
- dep[v] = curDep;
- gd[v].clear();
- ds[v].clear();
- allds[v] = {1};
- dist[v].clear();
- dist[v][v] = 0;
- for (int i = 0; i < sz(g[v]); i++) {
- int u = g[v][i];
- if (dep[u] < inf) {
- continue;
- }
- vector<pair<int, int>> vs;
- getVs(u, v, 1, inf, vs);
- ds[v].push_back({});
- for (int j = 0; j < sz(vs); j++) {
- int w = vs[j].first;
- int d = vs[j].second;
- if (d >= sz(allds[v])) {
- allds[v].resize(d + 1);
- }
- allds[v][d]++;
- if (d >= sz(ds[v].back())) {
- ds[v].back().resize(d + 1);
- }
- ds[v].back()[d]++;
- dist[v][w] = d;
- }
- int w = rebuild(u, curDep + 1);
- ts[v] += ts[w];
- p[w] = v;
- ppos[w] = sz(gd[v]);
- gd[v].push_back(w);
- }
- mxts[v] = ts[v] * 2;
- return v;
- }
- vector<int> getPath(int v) {
- vector<int> path;
- while (v != -1) {
- path.push_back(v);
- v = p[v];
- }
- return path;
- }
- void addEdge(int v, int u) {
- g[v].push_back(u);
- g[u].push_back(v);
- vector<int> pv = getPath(v), pu = getPath(u);
- int pr = -1, prpos = -1;
- while (!pv.empty()) {
- int cv = pv.back(), cu = pu.back();
- if (ts[cv] < ts[cu]) {
- swap(v, u);
- swap(pv, pu);
- swap(cv, cu);
- }
- if (ts[cv] + ts[cu] > mxts[cv]) {
- int curDep = dep[cv];
- vector<pair<int, int>> vs;
- getVs(cv, -1, 0, dep[cv], vs);
- for (int i = 0; i < sz(vs); i++) {
- int w = vs[i].first;
- dep[w] = inf;
- }
- int root = rebuild(cv, curDep);
- p[root] = pr;
- ppos[root] = prpos;
- if (pr != -1) {
- gd[pr][prpos] = root;
- }
- return;
- }
- p[cv] = pr;
- ppos[cv] = prpos;
- if (pr != -1) {
- gd[pr][prpos] = cv;
- }
- pv.pop_back();
- int pos = (pv.empty() ? -1 : ppos[pv.back()]);
- if (pos == -1) {
- pos = sz(gd[cv]);
- gd[cv].push_back(cu);
- ds[cv].push_back({});
- }
- ts[cv] += ts[cu];
- vector<pair<int, int>> vs;
- getVs(u, v, 0, dep[cu], vs);
- int du = dist[cv][v] + 1;
- for (int i = 0; i < sz(vs); i++) {
- int w = vs[i].first;
- int d = du + vs[i].second;
- dep[w]++;
- if (d >= sz(allds[cv])) {
- allds[cv].resize(d + 1);
- }
- allds[cv][d]++;
- if (d >= sz(ds[cv][pos])) {
- ds[cv][pos].resize(d + 1);
- }
- ds[cv][pos][d]++;
- dist[cv][w] = d;
- }
- pr = cv;
- prpos = pos;
- }
- int cu = pu.back();
- p[cu] = pr;
- ppos[cu] = prpos;
- }
- int get(int v, int d) {
- int res = 0;
- for (int u = v, pos = -1; u != -1; pos = ppos[u], u = p[u]) {
- int dvu = dist[u][v];
- int curd = d - dvu;
- if (curd < 0) {
- continue;
- }
- res += (curd < sz(allds[u]) ? allds[u][curd] : 0);
- if (pos != -1) {
- res -= (curd < sz(ds[u][pos]) ? ds[u][pos][curd] : 0);
- }
- }
- return res;
- }
- void solve() {
- for (int i = 0; i < n; i++) {
- g[i].clear();
- p[i] = -1;
- ppos[i] = -1;
- ts[i] = 1;
- mxts[i] = 2;
- dep[i] = 0;
- gd[i].clear();
- ds[i].clear();
- allds[i] = {1};
- dist[i].clear();
- dist[i][i] = 0;
- }
- int res = 0;
- for (int qq = 0; qq < q; qq++) {
- int t, a, b;
- scanf("%d%d%d", &t, &a, &b);
- if (t == 1) {
- int v = (a + res) % n;
- int u = (b + res) % n;
- addEdge(v, u);
- } else {
- int v = (a + res) % n;
- int d = (b + res) % n;
- res = get(v, d);
- printf("%d\n", res);
- }
- }
- }
- int main() {
- precalc();
- #ifdef DEBUG
- assert(freopen(TASK ".in", "r", stdin));
- assert(freopen(TASK ".out", "w", stdout));
- #endif
- while (read()) {
- solve();
- #ifdef DEBUG
- eprintf("Time %.2f\n", (double) clock() / CLOCKS_PER_SEC);
- #endif
- }
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement