Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include <bits/stdc++.h>
- using namespace std;
- mt19937 rr(random_device{}());
- struct item {
- int key, prior, cnt, sum;
- bool cycle = 0, rev = 0;
- item *l, *r, *parent;
- item() : l(nullptr), r(nullptr), parent(nullptr), cnt(1) {};
- item(int key, int prior) : l(nullptr), r(nullptr), key(key), parent(nullptr), cnt(1) {};
- };
- int h = 0;
- int cnt(item *t) {
- if (!t)
- return 0;
- return t->cnt;
- }
- void push(item *it) {
- if (it && it->rev) {
- it->rev = false;
- swap(it->l, it->r);
- if (it->l) it->l->rev ^= true;
- if (it->r) it->r->rev ^= true;
- }
- }
- void update(item *t) {
- if (t) {
- t->cnt = cnt(t->l) + cnt(t->r) + 1;
- }
- }
- void print(item *t) {
- if (t) {
- push(t);
- print(t->l);
- cout << t->key + 1 << " ";
- if (t->parent) {
- // cout << t->parent->key << " papa " << endl;
- }
- print(t->r);
- }
- }
- //void split(item * t, item * &l, item * &r, int pos, int add)
- pair<item *, item *> split(item *root, int key, int add) {
- if (root == nullptr)
- return make_pair(nullptr, nullptr);
- push(root);
- int cur = add + cnt(root->l);
- if (cur < key) {
- pair<item *, item *> splitted = split(root->r, key, cur + 1);
- root->r = splitted.first;
- if (splitted.first)
- splitted.first->parent = root;
- if (splitted.second)
- splitted.second->parent = nullptr;
- update(root);
- return make_pair(root, splitted.second);
- } else {
- pair<item *, item *> splitted = split(root->l, key, add);
- root->l = splitted.second;
- if (splitted.second)
- splitted.second->parent = root;
- if (splitted.first)
- splitted.first->parent = nullptr;
- update(root);
- return make_pair(splitted.first, root);
- }
- }
- item *merge(item *l, item *r) {
- if (!l || !r)
- return l ? l : r;
- else {
- push(l);
- push(r);
- if (l->prior > r->prior) {
- l->r = merge(l->r, r);
- l->r->parent = l;
- update(l);
- return l;
- } else {
- r->l = merge(l, r->l);
- r->l->parent = r;
- update(r);
- return r;
- }
- }
- }
- void reverse(item *&t, int l, int r) {
- item *t1, t2, t3;
- auto v = split(t, l, 0);
- auto v1 = split(v.second, r - l + 1, 0);
- v1.first->rev ^= true;
- t = merge(v.first, v1.first);
- t = merge(t, v1.second);
- // split (t, t1, t2, l);
- // split (t2, t2, t3, r-l+1);
- // t2->rev ^= true;
- // merge (t, t1, t2);
- // merge (t, t, t3);
- }
- item *get_root(item *t) {
- int cnt = 0;
- while (t && t->parent) {
- t = t->parent;
- cnt++;
- if (cnt == 10000000) {
- assert(0);
- }
- }
- return t;
- }
- void super_push(item *t) {
- if (t == nullptr) {
- return;
- }
- super_push(t->parent);
- push(t);
- }
- int get_number(item *t) {
- super_push(t);
- int res = cnt(t->l);
- int cn = 0;
- while (t) {
- if (t->parent) {
- if (t->parent->r == t) {
- res += cnt(t->parent->l) + 1;
- }
- }
- cn++;
- if (cn == 10000000) {
- assert(0);
- }
- t = t->parent;
- }
- return res;
- }
- const int MAXN = 1e5 + 69;
- item *a[MAXN];
- inline bool the_biggest(item *t) {
- if ((!t->parent && !t->r) || (t->parent && t->parent->r == t)) {
- return 1;
- }
- return 0;
- }
- int main() {
- // srand(time(nullptr));
- ios_base::sync_with_stdio(0);
- cin.tie(0);
- cout.tie(0);
- item *root = nullptr;
- int n, q, m, el;
- cin >> n >> q >> m;
- for (int i = 0; i < n; ++i) {
- a[i] = new item(i, rr());
- }
- for (int i = 0; i < q; ++i) {
- int fr, to;
- cin >> fr >> to;
- fr--, to--;
- item *r1 = get_root(a[fr]);
- item *r2 = get_root(a[to]);
- // print(r1);
- // cout << endl;
- // print(r2);
- // cout << endl;
- if (r1 == r2) {
- r1->cycle = 1;
- } else {
- if (!the_biggest(a[fr])) {
- reverse(r1, 0, cnt(r1) - 1);
- }
- if (the_biggest(a[to])) {
- reverse(r2, 0, cnt(r2) - 1);
- }
- r1 = merge(r1, r2);
- }
- }
- for (int i = 0; i < m; ++i) {
- char tp;
- cin >> tp;
- int fr, to;
- cin >> fr >> to;
- fr--, to--;
- if (tp == '+') {
- item *r1 = get_root(a[fr]);
- item *r2 = get_root(a[to]);
- if (r1 == r2 && r1->cycle) {
- assert(0);
- return 0;
- }
- if (r1 == r2) {
- r1->cycle = 1;
- } else {
- if (!the_biggest(a[fr])) {
- reverse(r1, 0, cnt(r1) - 1);
- }
- if (the_biggest(a[to])) {
- reverse(r2, 0, cnt(r2) - 1);
- }
- r1 = merge(r1, r2);
- }
- } else if (tp == '-') {
- item *r1 = get_root(a[fr]);
- int n1 = get_number(a[fr]);
- int n2 = get_number(a[to]);
- if (n1 > n2) {
- swap(fr, to);
- swap(n1, n2);
- // swap(r1, r2);
- }
- if (r1->cycle) {
- if (abs(n1 - n2) > 1) {
- r1->cycle = 0;
- continue;
- }
- auto v = split(r1, n1 + 1, 0);
- r1 = merge(v.second, v.first);
- r1->cycle = 0;
- } else if (!r1->cycle) {
- auto v = split(r1, n1 + 1, 0);
- } else {
- // assert(0);
- // return 0;
- }
- // cout << "result " << endl;
- // print(r1);
- // cout << endl;
- // print(r2);
- // cout << endl;
- } else {
- int n1 = get_number(a[fr]);
- int n2 = get_number(a[to]);
- item *r1 = get_root(a[fr]);
- item *r2 = get_root(a[to]);
- if (r1 == r2) {
- if (r1->cycle) {
- cout << max(min(abs(n1 - n2), cnt(r1) - abs(n1 - n2)) - 1, 0) << '\n';
- } else {
- cout << max(0, abs(n1 - n2) - 1) << '\n';
- }
- } else {
- cout << -1 << '\n';
- }
- }
- }
- // print(root);
- return 0;
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement