SHARE
TWEET

Untitled

a guest Jan 23rd, 2019 33 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. #ifdef DEBUG
  2. //#define _GLIBCXX_DEBUG
  3. #endif
  4.  
  5. #include <bits/stdc++.h>
  6.  
  7. using namespace std;
  8.  
  9. typedef long double ld;
  10.  
  11. #ifdef DEBUG
  12. #define eprintf(...) fprintf(stderr, __VA_ARGS__), fflush(stderr)
  13. #else
  14. #define eprintf(...) ;
  15. #endif
  16.  
  17. #define sz(x) ((int) (x).size())
  18. #define TASK "text"
  19.  
  20. const int inf = (int) 1.01e9;
  21. const long long infll = (long long) 1.01e18;
  22. const ld eps = 1e-9;
  23. const ld pi = acos((ld) -1);
  24.  
  25. #ifdef DEBUG
  26. mt19937 mrand(300);
  27. #else
  28. mt19937 mrand(chrono::steady_clock::now().time_since_epoch().count());
  29. #endif
  30.  
  31. int rnd(int x) {
  32.   return mrand() % x;
  33. }
  34.  
  35. void precalc() {
  36. }
  37.  
  38. const int maxn = (int) 1e5 + 5;
  39. int n, q;
  40.  
  41. bool read() {
  42.   if (scanf("%d%d", &n, &q) < 2) {
  43.     return false;
  44.   }
  45.   return true;
  46. }
  47.  
  48. vector<int> g[maxn];
  49. int p[maxn], ppos[maxn];
  50. int ts[maxn], mxts[maxn];
  51. int dep[maxn];
  52. vector<int> gd[maxn];
  53. vector<vector<int>> ds[maxn];
  54. vector<int> allds[maxn];
  55. map<int, int> dist[maxn];
  56.  
  57. void getVs(int v, int p, int d, int minDep, vector<pair<int, int>> &vs) {
  58.   vs.push_back(make_pair(v, d));
  59.   for (int i = 0; i < sz(g[v]); i++) {
  60.     int u = g[v][i];
  61.     if (u == p || dep[u] < minDep) {
  62.       continue;
  63.     }
  64.     getVs(u, v, d + 1, minDep, vs);
  65.   }
  66. }
  67.  
  68. int s[maxn];
  69.  
  70. void getS(int v, int p) {
  71.   s[v] = 1;
  72.   for (int i = 0; i < sz(g[v]); i++) {
  73.     int u = g[v][i];
  74.     if (u == p || dep[u] < inf) {
  75.       continue;
  76.     }
  77.     getS(u, v);
  78.     s[v] += s[u];
  79.   }
  80. }
  81.  
  82. int getCentroid(int v) {
  83.   getS(v, -1);
  84.   int alls = s[v];
  85.   int pv = -1;
  86.   while (true) {
  87.     int nv = -1;
  88.     for (int i = 0; i < sz(g[v]); i++) {
  89.       int u = g[v][i];
  90.       if (u == pv || dep[u] < inf) {
  91.         continue;
  92.       }
  93.       if (2 * s[u] > alls) {
  94.         nv = u;
  95.       }
  96.     }
  97.     if (nv == -1) {
  98.       break;
  99.     }
  100.     pv = v;
  101.     v = nv;
  102.   }
  103.   return v;
  104. }
  105.  
  106. int rebuild(int v, int curDep) {
  107.   v = getCentroid(v);
  108.   ts[v] = 1;
  109.   dep[v] = curDep;
  110.   gd[v].clear();
  111.   ds[v].clear();
  112.   allds[v] = {1};
  113.   dist[v].clear();
  114.   dist[v][v] = 0;
  115.   for (int i = 0; i < sz(g[v]); i++) {
  116.     int u = g[v][i];
  117.     if (dep[u] < inf) {
  118.       continue;
  119.     }
  120.     vector<pair<int, int>> vs;
  121.     getVs(u, v, 1, inf, vs);
  122.     ds[v].push_back({});
  123.     for (int j = 0; j < sz(vs); j++) {
  124.       int w = vs[j].first;
  125.       int d = vs[j].second;
  126.       if (d >= sz(allds[v])) {
  127.         allds[v].resize(d + 1);
  128.       }
  129.       allds[v][d]++;
  130.       if (d >= sz(ds[v].back())) {
  131.         ds[v].back().resize(d + 1);
  132.       }
  133.       ds[v].back()[d]++;
  134.       dist[v][w] = d;
  135.     }
  136.     int w = rebuild(u, curDep + 1);
  137.     ts[v] += ts[w];
  138.     p[w] = v;
  139.     ppos[w] = sz(gd[v]);
  140.     gd[v].push_back(w);
  141.   }
  142.   mxts[v] = ts[v] * 2;
  143.   return v;
  144. }
  145.  
  146. vector<int> getPath(int v) {
  147.   vector<int> path;
  148.   while (v != -1) {
  149.     path.push_back(v);
  150.     v = p[v];
  151.   }
  152.   return path;
  153. }
  154.  
  155. void addEdge(int v, int u) {
  156.   g[v].push_back(u);
  157.   g[u].push_back(v);
  158.   vector<int> pv = getPath(v), pu = getPath(u);
  159.   int pr = -1, prpos = -1;
  160.   while (!pv.empty()) {
  161.     int cv = pv.back(), cu = pu.back();
  162.     if (ts[cv] < ts[cu]) {
  163.       swap(v, u);
  164.       swap(pv, pu);
  165.       swap(cv, cu);
  166.     }
  167.     if (ts[cv] + ts[cu] > mxts[cv]) {
  168.       int curDep = dep[cv];
  169.       vector<pair<int, int>> vs;
  170.       getVs(cv, -1, 0, dep[cv], vs);
  171.       for (int i = 0; i < sz(vs); i++) {
  172.         int w = vs[i].first;
  173.         dep[w] = inf;
  174.       }
  175.       int root = rebuild(cv, curDep);
  176.       p[root] = pr;
  177.       ppos[root] = prpos;
  178.       if (pr != -1) {
  179.         gd[pr][prpos] = root;
  180.       }
  181.       return;
  182.     }
  183.     p[cv] = pr;
  184.     ppos[cv] = prpos;
  185.     if (pr != -1) {
  186.       gd[pr][prpos] = cv;
  187.     }
  188.     pv.pop_back();
  189.     int pos = (pv.empty() ? -1 : ppos[pv.back()]);
  190.     if (pos == -1) {
  191.       pos = sz(gd[cv]);
  192.       gd[cv].push_back(cu);
  193.       ds[cv].push_back({});
  194.     }
  195.     ts[cv] += ts[cu];
  196.     vector<pair<int, int>> vs;
  197.     getVs(u, v, 0, dep[cu], vs);
  198.     int du = dist[cv][v] + 1;
  199.     for (int i = 0; i < sz(vs); i++) {
  200.       int w = vs[i].first;
  201.       int d = du + vs[i].second;
  202.       dep[w]++;
  203.       if (d >= sz(allds[cv])) {
  204.         allds[cv].resize(d + 1);
  205.       }
  206.       allds[cv][d]++;
  207.       if (d >= sz(ds[cv][pos])) {
  208.         ds[cv][pos].resize(d + 1);
  209.       }
  210.       ds[cv][pos][d]++;
  211.       dist[cv][w] = d;
  212.     }
  213.     pr = cv;
  214.     prpos = pos;
  215.   }
  216.   int cu = pu.back();
  217.   p[cu] = pr;
  218.   ppos[cu] = prpos;
  219. }
  220.  
  221. int get(int v, int d) {
  222.   int res = 0;
  223.   for (int u = v, pos = -1; u != -1; pos = ppos[u], u = p[u]) {
  224.     int dvu = dist[u][v];
  225.     int curd = d - dvu;
  226.     if (curd < 0) {
  227.       continue;
  228.     }
  229.     res += (curd < sz(allds[u]) ? allds[u][curd] : 0);
  230.     if (pos != -1) {
  231.       res -= (curd < sz(ds[u][pos]) ? ds[u][pos][curd] : 0);
  232.     }
  233.   }
  234.   return res;
  235. }
  236.  
  237. void solve() {
  238.   for (int i = 0; i < n; i++) {
  239.     g[i].clear();
  240.     p[i] = -1;
  241.     ppos[i] = -1;
  242.     ts[i] = 1;
  243.     mxts[i] = 2;
  244.     dep[i] = 0;
  245.     gd[i].clear();
  246.     ds[i].clear();
  247.     allds[i] = {1};
  248.     dist[i].clear();
  249.     dist[i][i] = 0;
  250.   }
  251.   int res = 0;
  252.   for (int qq = 0; qq < q; qq++) {
  253.     int t, a, b;
  254.     scanf("%d%d%d", &t, &a, &b);
  255.     if (t == 1) {
  256.       int v = (a + res) % n;
  257.       int u = (b + res) % n;
  258.       addEdge(v, u);
  259.     } else {
  260.       int v = (a + res) % n;
  261.       int d = (b + res) % n;
  262.       res = get(v, d);
  263.       printf("%d\n", res);
  264.     }
  265.   }
  266. }
  267.  
  268. int main() {
  269.   precalc();
  270. #ifdef DEBUG
  271.   assert(freopen(TASK ".in", "r", stdin));
  272.   assert(freopen(TASK ".out", "w", stdout));
  273. #endif
  274.   while (read()) {
  275.     solve();
  276. #ifdef DEBUG
  277.     eprintf("Time %.2f\n", (double) clock() / CLOCKS_PER_SEC);
  278. #endif
  279.   }
  280.   return 0;
  281. }
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
Not a member of Pastebin yet?
Sign Up, it unlocks many cool features!
 
Top