Submission #965052

# Submission time Handle Problem Language Result Execution time Memory
965052 2024-04-18T04:22:36 Z obokaman Game (IOI13_game) C++17
10 / 100
13000 ms 9052 KB
#include <iostream>
#include <vector>
#include "game.h"

using namespace std;

#define debug false
typedef long long ll;

struct Node {
  Node *l, *r;
  int x;
  ll val;
  int prio;
  ll gcd;
};

struct RowNode {
  RowNode *l, *r;
  int x;
  Node* row;
  Node* thick_row;
  int prio;
};

Node* row(RowNode* t) {
  return t ? t->row : nullptr;
}

Node* thick_row(RowNode* t) {
  return t ? t->thick_row : nullptr;
}

ll gcd(Node* t) {
  return t ? t->gcd : -1;
}
ll val(Node* t) {
  return t ? t->val : -1;
}

ll gcdrec(ll a, ll b) {
  return a == 0 ? b : gcdrec(b%a, a); 
}

ll gcd(ll a, ll b) {
  if (a == -1 || b == -1) return a == -1 ? b : a;
  return gcdrec(a, b);
}

Node* init_node(int x, ll val) {
  Node* t = new Node;
  t->l = t->r = nullptr;
  t->x = x;
  t->val = t->gcd = val;
  t->prio = rand();
  return t;
}

void update(Node* t) {
  if (t) {
    t->gcd = gcd(gcd(gcd(t->l), ll(t->val)), gcd(t->r));
  }
}

void split(Node* t, Node*& l, Node*& r, int x) {
  if (!t) {
    l = r = nullptr;
  } else {
    if (x < t->x) {
      r = t;
      split(t->l, l, t->l, x);
    } else {
      l = t;
      split(t->r, t->r, r, x);
    }
    update(t);
  }
}

void merge(Node*& t, Node* l, Node* r) {
  if (!l || !r) {
    t = l ? l : r;
  } else {
    if (l->prio < r->prio) {    
      t = l;
      merge(t->r, t->r, r);
    } else {
      t = r;
      merge(t->l, l, t->l);
    }
    update(t);
  } 
}

void print(Node* t) {
  if (t) {
    cout << "[";
    print(t->l);
    cout << " " << t->x << "|" << t->val << "|" << t->gcd << " ";
    print(t->r);
    cout << "]";
  }
}

void print(RowNode* t, int indent = 0) {
  if (t) {
    indent+=2;
    print(t->l, indent);
    cout << endl;
    
    string sp(indent, ' ');
    cout << sp << "x=" << t->x << endl;
    cout << sp << "row=";
    print(t->row);
    cout << endl << sp << "thickrow=";
    print(t->thick_row);
    cout << endl;
    cout << endl;
    print(t->r, indent);
    indent-=2;
  }
}

void update_x(Node*& t, int x, ll val) {
  Node* t1, *t2, *t3;
  split(t, t1, t2, x-1);
  split(t2, t2, t3, x);
  if (debug) {
    cout << "Updating:";
    print(t2);
    cout << endl;
  }
  if (!t2) t2 = init_node(x, val);
  else t2->val = t2->gcd = val;
  merge(t, t1, t2);
  merge(t, t, t3);
}

ll gcdRS(Node* t, int R, int S) {
  Node* t1, *t2, *t3;
  split(t, t1, t2, R-1);
  split(t2, t2, t3, S);
  ll res = gcd(t2);
  merge(t, t1, t2);
  merge(t, t, t3);
  return res;
}


// gcd([x, \infy))
ll queryR(RowNode* t, int x, int R, int S) {
  if (debug) {
    cout << "QueryR: x=" << x << endl;
    print(t);
    cout << endl << endl;
  }
  if (!t) return -1;
  else if (x < t->x) return gcd(gcdRS(thick_row(t->r), R, S),
				gcd(gcdRS(row(t), R, S),
				    queryR(t->l, x, R, S)));
  else if (x == t->x) return gcd(gcdRS(thick_row(t->r), R, S),
				 gcdRS(row(t), R, S));
  else return queryR(t->r, x, R, S);
}

// gcd((-\infy, x])
ll queryL(RowNode* t, int x, int R, int S) {
  if (debug) {
    cout << "QueryL: x=" << x << endl;
    print(t);
    cout << endl << endl;
  }
  if (!t) return -1;
  else if (x > t->x) return gcd(gcdRS(thick_row(t->l), R, S),
				gcd(gcdRS(row(t), R, S),
				    queryL(t->r, x, R, S)));
  else if (x == t->x) return gcd(gcdRS(thick_row(t->l), R, S),
				 gcdRS(row(t), R, S));
  else return queryL(t->l, x, R, S);
}

// gcd of [P, Q]x[R, S]
ll query(RowNode* t, int P, int Q, int R, int S) {
  if (!t) return -1;
  if (t->x < P) return query(t->r, P, Q, R, S);
  else if (t->x > Q) return query(t->l, P, Q, R, S);
  else {
    if (debug) {
      cout << P << "<=" << t->x << "<=" << Q << endl;
      cout << "Going for QueryR and QueryL" << endl;
    }
    return gcd(gcdRS(row(t), R, S), gcd(queryR(t->l, P, R, S),
					queryL(t->r, Q, R, S)));
  }
}

ll find_gcd(Node* t, int Q) {
  if (!t) return -1;
  if (t->x == Q) return t->val;
  else {
    return find_gcd(Q < t->x ? t->l : t->r, Q);
  }
}

void pointUpdateThickrow(RowNode*& t, int Q, ll val) {
  // We don't need to fully recalculate thickrow, because only x=Q had
  // changed.
  Node* t1, *t2, *t3;
  split(t->thick_row, t1, t2, Q-1);
  split(t2, t2, t3, Q);
  ll newval = gcd( find_gcd(thick_row(t->l), Q),
		   gcd( find_gcd(thick_row(t->r), Q), val) );
  if (!t2) t2 = init_node(Q, newval);
  else t2->val = t2->gcd = newval;

  merge(t->thick_row, t1, t2);
  merge(t->thick_row, t->thick_row, t3);      
}

RowNode* find(RowNode* t, int P) {
  if (!t) {
    return nullptr;
  }
  else if (P < t->x) {
    return find(t->l, P);
  }
  else if (P > t->x) {
    return find(t->r, P);
  }
  else {
    return t;
  }
}

void copy(Node* src, Node*& dst) {
  if (!src) dst = nullptr;
  else {
    dst = new Node;
    copy(src->l, dst->l);
    copy(src->r, dst->r);
    dst->x = src->x;
    dst->val = src->val;
    dst->prio = src->prio;
    dst->gcd = src->gcd;
  }
}

Node* join(Node* t1, Node* t2) {
  Node* t;
  if (!t1 && !t2) t = nullptr;
  else if (!t1) copy(t2, t);
  else if (!t2) copy(t1, t);
  else {
    if (t1->prio < t2->prio) swap(t1, t2);
    t = new Node;
    Node* t2l, *t2x, *t2r;
    split(t2, t2l, t2x, t1->x-1);
    split(t2x, t2x, t2r, t1->x);
    t->x = t1->x;
    // Maybe I don't need t->val for thickrows?
    t->val = gcd(val(t1), val(t2x));
    t->gcd = gcd(gcd(t1), gcd(t2));
    t->prio = t1->prio;
    t->l = join(t1->l, t2l);
    t->r = join(t1->r, t2r);
    merge(t2, t2l, t2x);
    merge(t2, t2, t2r);
  }
  return t;
}

// P in l.
void split(RowNode* t, RowNode*& l, RowNode*& r, int P) {
  if (!t) {
    l = r = nullptr;
  } else {
    if (P < t->x) {
      r = t;
      split(t->l, l, t->l, P); 
    } else {
      l = t;
      split(t->r, t->r, r, P);
    }
    t->thick_row = join(join(thick_row(t->l), t->row), thick_row(t->r));
  }
}

void set_rec(RowNode*& t, int P, int Q, ll val, int prio) {
  if (!t) {
    if (debug) {
      cout << "new RowNode" << endl;
    }
    t = new RowNode;
    t->l = t->r = nullptr;
    t->x = P;
    t->row = init_node(Q, val);
    t->prio = prio;
  } else {
    if (prio > t->prio) {
      if (debug) {
	cout << "insert RowNode" << endl;
      }
      // We know (from previous find(...)) that P is not available, we
      // will insert it here.
      RowNode* child = t;
      t = new RowNode;
      t->l = t->r = nullptr;
      t->x = P;
      split(child, t->l, t->r, P);
      t->row = init_node(Q, val);
      // (Q,val) will be updated as part of updateThickrow
      t->thick_row = join(thick_row(t->l), thick_row(t->r));
      t->prio = prio;
    } else if (P < t->x) {
      if (debug) {
	cout << "set_rec t->l" << endl;
      }
      set_rec(t->l, P, Q, val, prio);
    } else if (P == t->x) {
      if (debug) {
	cout << "update_x" << endl;
      }
      update_x(t->row, Q, val);
    } else {
      if (debug) {
	cout << "set_rec t->r" << endl;
      }
      set_rec(t->r, P, Q, val, prio);
    }
  }
  pointUpdateThickrow(t, Q, val);
}

void set(RowNode*& t, int P, int Q, ll val) {
  if (find(t, P)) {
    if (debug) {
      cout << "Found P=" << P << endl;
    }
    set_rec(t, P, Q, val, 0);
  } else {
    if (debug) {
      cout << "Not found P=" << P << endl;
    }
    set_rec(t, P, Q, val, rand());
  }
}


RowNode* globalt = nullptr;
vector<vector<ll> > W;
void init(int R, int C) {
  W.resize(R, vector<ll>(C)); 
}
void update(int P, int Q, ll K) {
  //  set(globalt, P, Q, K);
  W[P][Q] = K;
}
ll calculate(int P, int Q, int R, int S) {
  ll slow = -1;
  for (int i=P;i<=R;++i) {
    for (int j=Q;j<=S;++j) {
      slow = gcd(slow, W[i][j]);
    }
  }
  // ll res = query(globalt, P, R, Q, S);
  // if (slow != res) {
  //   cout << "Error! " << P << " " << Q << " " << R << " " << S << endl;
  //   cout << "Actual: " << slow << "  Returned:" << res << endl;
  // }
  return slow == -1 ? 0 : slow;
}

//int main() {
int mymain() {
  string Q;
  init(10, 10);
  while (cin >> Q) {
    if (Q == "U") {
      int P, Q;
      ll val;
      cin >> P >> Q >> val;
      update(P, Q, val);
    } else if (Q == "C") {
      int P, Q, R, S;
      cin >> P >> Q >> R >> S;
      cout << calculate(P, Q, R, S) << endl;
      //      cout << query(t, P, R, Q, S) << endl;
    }
    if (debug) {
      cout << "After:";
      print(globalt);
      cout << endl;
    }
  }
  return 0;
}
# Verdict Execution time Memory Grader output
1 Correct 0 ms 348 KB Output is correct
2 Correct 1 ms 520 KB Output is correct
3 Correct 1 ms 600 KB Output is correct
4 Correct 1 ms 348 KB Output is correct
5 Correct 1 ms 348 KB Output is correct
6 Correct 0 ms 348 KB Output is correct
7 Correct 0 ms 348 KB Output is correct
8 Correct 1 ms 348 KB Output is correct
9 Correct 1 ms 432 KB Output is correct
10 Correct 1 ms 348 KB Output is correct
11 Correct 1 ms 432 KB Output is correct
12 Correct 1 ms 348 KB Output is correct
# Verdict Execution time Memory Grader output
1 Correct 1 ms 344 KB Output is correct
2 Correct 1 ms 344 KB Output is correct
3 Correct 1 ms 600 KB Output is correct
4 Execution timed out 13025 ms 9048 KB Time limit exceeded
5 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 348 KB Output is correct
2 Correct 1 ms 516 KB Output is correct
3 Correct 1 ms 348 KB Output is correct
4 Correct 1 ms 440 KB Output is correct
5 Correct 1 ms 348 KB Output is correct
6 Correct 1 ms 348 KB Output is correct
7 Correct 1 ms 344 KB Output is correct
8 Correct 0 ms 348 KB Output is correct
9 Correct 1 ms 348 KB Output is correct
10 Correct 1 ms 348 KB Output is correct
11 Correct 1 ms 348 KB Output is correct
12 Execution timed out 13032 ms 8692 KB Time limit exceeded
13 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 344 KB Output is correct
2 Correct 1 ms 348 KB Output is correct
3 Correct 1 ms 348 KB Output is correct
4 Correct 1 ms 348 KB Output is correct
5 Correct 1 ms 348 KB Output is correct
6 Correct 1 ms 432 KB Output is correct
7 Correct 1 ms 436 KB Output is correct
8 Correct 1 ms 344 KB Output is correct
9 Correct 1 ms 348 KB Output is correct
10 Correct 1 ms 348 KB Output is correct
11 Correct 1 ms 344 KB Output is correct
12 Execution timed out 13023 ms 9048 KB Time limit exceeded
13 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Correct 1 ms 348 KB Output is correct
2 Correct 1 ms 440 KB Output is correct
3 Correct 1 ms 344 KB Output is correct
4 Correct 1 ms 348 KB Output is correct
5 Correct 1 ms 348 KB Output is correct
6 Correct 0 ms 344 KB Output is correct
7 Correct 1 ms 348 KB Output is correct
8 Correct 1 ms 604 KB Output is correct
9 Correct 1 ms 348 KB Output is correct
10 Correct 1 ms 348 KB Output is correct
11 Correct 1 ms 348 KB Output is correct
12 Execution timed out 13048 ms 9052 KB Time limit exceeded
13 Halted 0 ms 0 KB -