제출 #967334

#제출 시각아이디문제언어결과실행 시간메모리
967334obokaman게임 (IOI13_game)C++17
100 / 100
4171 ms65652 KiB
#include <iostream>
#include <vector>
#include <string>
#include "game.h"

using namespace std;

typedef long long ll;

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

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), 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 update_x(Node*& t, int x, ll val) {
  Node* t1, *t2, *t3;
  split(t, t1, t2, x-1);
  split(t2, t2, t3, x);
  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;
}
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);
  }
}

struct SSTNode {
  SSTNode *l = nullptr, *r = nullptr;
  Node* row = nullptr;
};
Node* row(SSTNode* t) {
  return t ? t->row : nullptr;
}
// t is [a, b), x \in [a,b)
void set(SSTNode*& t, int P, int Q, ll val, int a, int b) {
  if (!t) t = new SSTNode;
  if (b > a+1) {
    int m = (a+b)/2;
    if (P < m) set(t->l, P, Q, val, a, m);
    else set(t->r, P, Q, val, m, b);
    // Update row, using that most gcd are not expected to change.
    Node* t1, *t2, *t3;
    split(t->row, t1, t2, Q-1);
    split(t2, t2, t3, Q);
    ll new_gcd = gcd(val, gcd(find_gcd(row(t->l), Q), find_gcd(row(t->r), Q)));
    if (!t2) {
      t2 = init_node(Q, new_gcd);
    } else {
      t2->val = t2->gcd = new_gcd;
    }
    merge(t->row, t1, t2);
    merge(t->row, t->row, t3);
  } else {
    update_x(t->row, Q, val);
  }
}
// gcd of [P, Q]x[R, S], knowing that t covers [a,b)
ll query(SSTNode* t, int P, int Q, int R, int S, int a, int b) {
  if (!t || Q < a || P >= b || a >= b) return -1;
  if (P <= a && b-1 <= Q) {
    ll res = gcdRS(t->row, R, S);
    return res;
  } else {
    ll m = (a+b)/2;
    ll res = gcd(query(t->l, P, Q, R, S, a, m),
		 query(t->r, P, Q, R, S, m, b));
    return res;
  }
}

SSTNode* gn = nullptr;
int globalRows = -1;
int Rp2 = 1;

void init(int R, int C) {
  globalRows = R;
  while (Rp2 <= R) Rp2*=2;
}
void update(int P, int Q, ll K) {
  set(gn, P, Q, K, 0, Rp2);
}
ll calculate(int P, int Q, int R, int S) {
  ll res = query(gn, P, R, Q, S, 0, Rp2);
  return res == -1 ? 0 : res;
}
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...
#Verdict Execution timeMemoryGrader output
Fetching results...