Advertisement
bibaboba12345

Untitled

Jan 12th, 2023
78
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 5.84 KB | None | 0 0
  1. // clang-format off
  2. #define _CRT_SECURE_NO_WARNINGS
  3. #include <iostream>
  4. #include <iomanip>
  5. #include <bitset>
  6. #include <vector>
  7. #include <algorithm>
  8. #include <random>
  9. #include <map>
  10. #include <string>
  11. #include <set>
  12. #include <deque>
  13. #include <string>
  14. #include <cassert>
  15.  
  16. #pragma GCC optimize("Ofast")
  17.  
  18. using namespace std;
  19. const int N = 2e5 + 7, MOD = 1e9 + 7, C = 1000, C2 = 10;
  20. const long long INF = 1e18;
  21. const long double EPS = 1e-9;
  22.  
  23. mt19937 rnd;
  24.  
  25. struct Node {
  26. Node* l, * r, * p;
  27. int sz;
  28. int x, y;
  29. bool IsCycle, push;
  30. Node(int val) {
  31. l = nullptr;
  32. r = nullptr;
  33. p = nullptr;
  34. IsCycle = 0;
  35. push = 0;
  36. sz = 1;
  37. x = val;
  38. y = rnd();
  39. }
  40. };
  41.  
  42. void push(Node* v) {
  43. if (v == nullptr || v->push == 0) {
  44. return;
  45. }
  46. v->push = 0;
  47. swap(v->l, v->r);
  48. if (v->l != nullptr) {
  49. v->l->push ^= 1;
  50. }
  51. if (v->r != nullptr) {
  52. v->r->push ^= 1;
  53. }
  54. }
  55.  
  56. void recalc(Node* v) {
  57. if (v == nullptr) {
  58. return;
  59. }
  60. v->sz = 1;
  61. if (v->l != nullptr) {
  62. v->l->p = v;
  63. v->sz += v->l->sz;
  64. }
  65. if (v->r != nullptr) {
  66. v->r->p = v;
  67. v->sz += v->r->sz;
  68. }
  69. }
  70.  
  71. int sz(Node* v) {
  72. if (v == nullptr) {
  73. return 0;
  74. }
  75. return v->sz;
  76. }
  77.  
  78.  
  79. struct CartesianTree {
  80. Node* nodes[N];
  81. int len;
  82. pair<Node*, Node*> split(Node* v, int k) {
  83. if (v != nullptr) {
  84. v->IsCycle = 0;
  85. }
  86. if (v == nullptr) {
  87. return { nullptr, nullptr };
  88. }
  89. push(v);
  90. if (sz(v->l) >= k) {
  91. if(v->l != nullptr)
  92. v->l->p = nullptr;
  93. auto res = split(v->l, k);
  94. v->l = res.second;
  95. recalc(v);
  96. return { res.first, v };
  97. }
  98. else {
  99. if(v->r != nullptr)
  100. v->r->p = nullptr;
  101. auto res = split(v->r, k - sz(v->l) - 1);
  102. v->r = res.first;
  103. recalc(v);
  104. return { v, res.second };
  105. }
  106. }
  107. Node* merge(Node* l, Node* r) {
  108. if (l != nullptr) {
  109. l->IsCycle = 0;
  110. }
  111. if (r != nullptr) {
  112. r->IsCycle = 0;
  113. }
  114. push(l);
  115. push(r);
  116. if (l == nullptr) return r;
  117. if (r == nullptr) return l;
  118.  
  119. if (l->y > r->y) {
  120. l->r = merge(l->r, r);
  121. recalc(l);
  122. return l;
  123. }
  124. else {
  125. r->l = merge(l, r->l);
  126. recalc(r);
  127. return r;
  128. }
  129. }
  130.  
  131. void rev(Node* v) {
  132. v->push ^= 1;
  133. }
  134.  
  135. void PushUp(Node* v) {
  136. vector<Node*> kek;
  137. kek.clear();
  138. while (v->p != nullptr) {
  139. kek.push_back(v);
  140. v = v->p;
  141. }
  142. kek.push_back(v);
  143. reverse(kek.begin(), kek.end());
  144. for (auto u : kek) {
  145. push(u);
  146. }
  147. }
  148.  
  149. void build(int n) {
  150. for (int i = 1; i <= n; i++) {
  151. auto nn = new Node(i);
  152. nodes[i] = nn;
  153. }
  154. }
  155. int GetInd(Node* v) {
  156. PushUp(v);
  157. int lft = sz(v->l);
  158. while (v->p != nullptr) {
  159. if (v == v->p->r) {
  160. lft++;
  161. lft += sz(v->p->l);
  162. }
  163. v = v->p;
  164. }
  165. return lft;
  166. }
  167. int GetParent(Node* v) {
  168. PushUp(v);
  169. while (v->p != nullptr) {
  170. v = v->p;
  171. }
  172. return v->x;
  173. }
  174.  
  175. void unite(int u, int v) {
  176. int p1 = GetParent(nodes[u]);
  177. int p2 = GetParent(nodes[v]);
  178. if (p1 == p2) {
  179. nodes[p1]->IsCycle = 1;
  180. }else{
  181. int i1 = GetInd(nodes[u]);
  182. int i2 = GetInd(nodes[v]);
  183. if (i1 == 0 && i2 == 0) {
  184. rev(nodes[p1]);
  185. merge(nodes[p1], nodes[p2]);
  186. return;
  187. }
  188. if (i1 == 0) {
  189. rev(nodes[p1]);
  190. merge(nodes[p1], nodes[p2]);
  191. return;
  192. }
  193. merge(nodes[p1], nodes[p2]);
  194. }
  195. }
  196.  
  197. void break_edge(int u, int v) {
  198. int p = GetParent(nodes[u]);
  199. int ind1 = GetInd(nodes[u]);
  200. int ind2 = GetInd(nodes[v]);
  201. if (!nodes[p]->IsCycle) {
  202. split(nodes[p], max(ind1, ind2));
  203. }
  204. else {
  205. if (max(ind1, ind2) == nodes[p]->sz - 1 && min(ind1, ind2) == 0) {
  206. nodes[p]->IsCycle = 0;
  207. return;
  208. }
  209. auto res = split(nodes[p], max(ind1, ind2));
  210. merge(res.second, res.first);
  211. }
  212. }
  213.  
  214.  
  215. int distance(int u, int v) {
  216. int p1 = GetParent(nodes[u]);
  217. int p2 = GetParent(nodes[v]);
  218. if (p1 != p2) {
  219. return 0;
  220. }
  221. int i1 = GetInd(nodes[v]);
  222. int i2 = GetInd(nodes[u]);
  223. int dist = abs(i1 - i2);
  224. if (nodes[p1]->IsCycle) {
  225. return min(dist, nodes[p1]->sz - dist);
  226. }
  227. return dist;
  228. }
  229. };
  230.  
  231. CartesianTree CT;
  232.  
  233. int n, m, q;
  234.  
  235. signed main() {
  236. #ifdef _DEBUG
  237. freopen("input.txt", "r", stdin);
  238. #else
  239. std::ios::sync_with_stdio(false);
  240. cin.tie(0);
  241. #endif
  242. cin >> n >> m >> q;
  243. CT.build(n);
  244. for (int i = 1; i <= m; i++) {
  245. int u, v;
  246. cin >> u >> v;
  247. CT.unite(u, v);
  248. }
  249. for (int i = 0; i < q; i++) {
  250. char t;
  251. int u, v;
  252. cin >> t >> u >> v;
  253. if (t == '+') {
  254. CT.unite(u, v);
  255. }
  256. if (t == '-') {
  257. CT.break_edge(u, v);
  258. }
  259. if (t == '?') {
  260. if (u == v) {
  261. cout << "0\n";
  262. continue;
  263. }
  264. cout << CT.distance(u, v) - 1 << "\n";
  265. }
  266. }
  267. }
  268.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement