Submission #746559

# Submission time Handle Problem Language Result Execution time Memory
746559 2023-05-22T18:51:50 Z asdf412 Seesaw (JOI22_seesaw) C++14
0 / 100
771 ms 62020 KB
#include <bits/stdc++.h>
#define ll long long
#define ii pair<int, int>
#define F first
#define S second

using namespace std;

random_device random_seed;
mt19937 mt(random_seed());

struct tree {

  struct Node {
    pair<int, int> key; // Changed key type to pair<int, int>
    int pri, si;
    ll sum;
    int idx; // Index of the node
    Node *l, *r;

    Node(pair<int, int> k, int i) {
      key = k;
      pri = mt();
      si = 1;
      sum = k.F;
      idx = i;
      l = r = nullptr;
    }
  };
  unordered_map<int, int> mp;

  Node *root = nullptr;

  int siz() { 
    if (mp.empty()) return 0;
    return mp.size(); 
  }

  unordered_map<int, int> getmp() {
    return mp;
  }

  int si(Node *root) {
    if (!root) return 0;
    return root->si;
  }

  ll sum(Node *root) {
    if (!root) return 0;
    return root->sum;
  }

  void upd(Node *root) {
    if (!root) return;
    root->si = 1 + si(root->l) + si(root->r);
    root->sum = root->key.F + sum(root->l) + sum(root->r);
  }

  void split(Node *root, int k, Node *&l, Node *&r) {
    if (!root) {
      l = r = nullptr;
      return;
    }
    if (si(root->l) < k) {
      split(root->r, k - si(root->l) - 1, root->r, r);
      l = root;
    } else {
      split(root->l, k, l, root->l);
      r = root;
    }
    upd(root);
  }

  void merge(Node *&root, Node *l, Node *r) {
    if (!l) {
      root = r;
      return;
    }
    if (!r) {
      root = l;
      return;
    }
    if (l->pri < r->pri) {
      merge(l->r, l->r, r);
      root = l;
    } else {
      merge(r->l, l, r->l);
      root = r;
    }
    upd(root);
  }

  void insert(int i, pair<int, int> k) {
    //cout << "inserted " << i << ' ' << k.F << ' ' << k.S << '\n';
    Node *l, *r, *t = new Node(k, i);
    split(root, i - 1, l, r);
    merge(root, l, t);
    merge(root, root, r);
  }

  void erase(int i) {
    Node *l, *r, *mi;
    split(root, i - 1, l, mi);
    split(mi, 1, mi, r);
    delete mi;
    merge(root, l, r);
  }

  ll getsum(int ql, int qr) {
    Node *l, *r, *mi;
    split(root, ql - 1, l, mi);
    split(mi, qr - ql + 1, mi, r);
    ll sum = mi->sum;
    merge(root, l, mi);
    merge(root, root, r);
    return sum;
  }

  pair<int, int> access(int i) {
    Node *curr = root;
    while (curr) {
      int l = si(curr->l);
      if (l == i) {
        return curr->key;
      } else if (l < i) {
        curr = curr->r;
        i -= l + 1;
      } else {
        curr = curr->l;
      }
    }
    return make_pair(-1, -1); // Index out of range
  }

  int lob(pair<int, int> val) {
    Node *curr = root;
    int result = 0;
    while (curr) {
      if (curr->key < val) {
        result += si(curr->l) + 1;
        curr = curr->r;
      } else {
        curr = curr->l;
      }
    }
    return result + 1;
    
  }

  void insert1(int pos, int val) {
    auto it = mp.find(pos);
    //int lo = lowerBoundIndex({val, -1});
    
    if (it == mp.end()) {
      int id = lob({val, pos});
      //cout << "not found wor low " << id << '\n';
      if (id == -1) insert(mp.size() + 1, {val, pos});
      else insert(id, {val, pos});
      mp[pos] = val;
      return;
    } 

    ii tmp = {mp[pos], pos};
    int lo = lob(tmp);
    erase(lo);
    int id = lob({val, pos});
    //if (mp[pos] < val) lo--;
    //cout << "wor low " << id << ' ' << lo  << ' ' << mp[pos] << '\n';
    
    if (lo == -1) lo = mp.size();
    if (id == -1) insert(mp.size() + 1, {val, pos});
    else insert(id, {val, pos});
    mp[pos] = val;
  }

  ll sum1(int a, int b) {
    int l = lob({a, 0});
    int r = lob({b, 1e9});
    //ii tk = access(r);
    r--;
    //if (t.F > b) r--; 
    //cout << "low sum " << l << ' ' << r << '\n';   
    if (l > r) return 0;
    //if (l == r) return tk.F;
    return getsum(l, r);
  }

  void prn(Node *root) {
    if (!root) return;
    upd(root);
    prn(root->l);
    cout << "[ " << root->key.F << ' ' << root->key.S << " ] ";
    prn(root->r);
  }

  void prn1(Node *root) {
    if (!root) return;
    upd(root);
    prn(root->l);
    cout << root->key.S << ' ';
    prn(root->r);
  }

  void prn() {
    cout << " treap \n";
    prn(root);
    cout << '\n';
    //prn1(root);
    cout << '\n';
  }
};

int N, Q;

struct Seg {
  tree t;
  int lo, hi;
  int il = -1, ir = -1;

  Seg(int a, int b) : lo(a), hi(b) {}

  Seg() : lo() {}
};

int curr = 0;

Seg seg[200000];

void upd(int idx, int pos, int val) {
  int l = seg[idx].lo, r = seg[idx].hi, mi = (l + r) >> 1;

  if (l == r) {
    seg[idx].t.insert1(pos, val);
    return;
  }
  
  int tr = (pos <= mi ? seg[idx].il : seg[idx].ir);
  bool lr = pos <= mi ? 1 : 0; // 1 left 0 right
  if (tr == -1) {
    curr++;
    if (lr) seg[idx].il = curr;
    else seg[idx].ir = curr;
    seg[curr] = Seg(pos, pos);
    seg[curr].t.insert1(pos, val);
  } else if (seg[tr].lo <= pos && pos <= seg[tr].hi) {
    upd(tr, pos, val);
  } else {
    do {
      if (pos <= mi) r = mi;
      else l = mi + 1;
      mi = (l + r) >> 1;
    } while ((pos <= mi) == (seg[tr].lo <= mi));

    curr++;
    seg[curr] = Seg(l, r);
    if (seg[tr].lo <= mi) seg[curr].il = tr;
    else seg[curr].ir = tr;

    if (lr) seg[idx].il = curr;
    else seg[idx].ir = curr;
    upd(curr, pos, val);
  }  
  //cout << "updateerror in " << l << ' ' << r << '\n';
  seg[idx].t.insert1(pos, val);
  int tl = seg[idx].il, trr = seg[idx].ir;
  int sil = seg[tl].t.siz();
  int sir = seg[trr].t.siz();
  if (sil + sir != seg[idx].t.siz()) {
    unordered_map<int, int> tm, tm1;
    if (tl != -1) tm = seg[tl].t.getmp();
    if (trr != -1) tm1 = seg[trr].t.getmp();
    for (auto i : tm) seg[idx].t.insert1(i.F, i.S);
    for (auto i : tm1) seg[idx].t.insert1(i.F, i.S);
  }
  

  /*
  if (root->l == NULL)
    root->l = new Seg(l, mi);
  if (root->r == NULL)
    root->r = new Seg(mi + 1, r);

  if (pos <= mi) upd(root->l, pos, val);
  else upd(root->r, pos, val);
  root->t.insert1(pos, val);
  */

  //root->t.prn();
}

ll qur(int idx, int ql, int qr, int a, int b) {
  if (idx == -1) return 0;
  int l = seg[idx].lo, r = seg[idx].hi, mi = (l + r) >> 1;

  //cout << "error in " << l << ' ' << r << '\n';
  //root->t.prn();
  
  if (l > qr || r < ql) 
    return 0;

  if (ql <= l && r <= qr) {
    ll ts = seg[idx].t.sum1(a, b);
    //cout << "return " << ts << '\n';
    return ts;
  }

  return qur(seg[idx].il, ql, qr, a, b) + qur(seg[idx].ir, ql, qr, a, b);
}

int cal(ll x) {
  return abs((x - 69) % min(420, N / 8 + 1));
}

using namespace chrono;


void prn(int idx) {
  if (idx == -1) return;
  prn(seg[idx].il);
  cout << "range : " << seg[idx].lo << ' ' << seg[idx].hi << '\n';
  seg[idx].t.prn();
  prn(seg[idx].ir);

}

void prn1(int idx) {
  cout << "currently seg \n";
  prn(idx);
  cout << '\n';
}

int ar[5005];

int main() {
  ios_base::sync_with_stdio(false); cin.tie(NULL);
  auto start = high_resolution_clock::now();
  
  //freopen("9.in", "r", stdin);
  //freopen("t3.sol", "w", stdout);

  
  N = 1e9, Q = 5e4;

  seg[0].lo = 0; seg[0].hi = N;
  int C = 0;
  while (Q--) {
    int X = mt(); 
    if (X&1 == 1) {
      int Pos = mt() % N, Val = mt(); 
      upd(0, Pos, Val);
    }
    else {
      int L, R, A, B;
      L = mt() % N, R = mt() % N, A = mt(), B = mt();
      if (L > R) swap(L, R);
      L += C; R += C;
      ll sum = qur(0, L, R, A, B);
      R = min(R, N);
      C = cal(sum);
      //cout << "sum of range " << C << ' ' << L << ' ' << R << " = " << sum << '\n';
      //cout << sum << '\n';
    }    
  }
  
  
  
  /*
  cin >> N >> Q;
  //if (N <= 10000) N = 10000;
  //Seg *root = new Seg(0, N); 
  seg[0].lo = 0; seg[0].hi = N;
  
  int C = 0;
  while (Q--) {
    int X; cin >> X;
    if (X == 1) {
      int Pos, Val; 
      cin >> Pos >> Val;
      upd(0, Pos, Val);
    } else {
      int L, R, A, B;
      cin >> L >> R >> A >> B;
      L += C; R += C;
      ll sum = qur(0, L, R, A, B);
      R = min(R, N);
      C = cal(sum);
      //cout << "sum of range " << C << ' ' << L << ' ' << R << " = " << sum << '\n';
      cout << sum << '\n';
      //prn1(0);
    }    
    
  }

  */

  auto stop = high_resolution_clock::now();
  auto duration = duration_cast<microseconds>(stop - start);

  cout << "Time taken by program: " << double(duration.count())/1000000 << " seconds\n"; 
  cout << curr << '\n';

  return 0;
}

/*
10 7
1 1 3
1 2 5
1 9 4
2 2 5 2 5
1 7 5
1 5 7
2 4 8 6 10

5
7

3 5 4 5 7 9 4 2 5 6

*/

Compilation message

seesaw.cpp: In function 'long long int qur(int, int, int, int, int)':
seesaw.cpp:293:41: warning: unused variable 'mi' [-Wunused-variable]
  293 |   int l = seg[idx].lo, r = seg[idx].hi, mi = (l + r) >> 1;
      |                                         ^~
seesaw.cpp: In function 'int main()':
seesaw.cpp:348:13: warning: suggest parentheses around comparison in operand of '&' [-Wparentheses]
  348 |     if (X&1 == 1) {
      |           ~~^~~~
# Verdict Execution time Memory Grader output
1 Incorrect 771 ms 62020 KB Expected double, but "Time" found
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 771 ms 62020 KB Expected double, but "Time" found
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 771 ms 62020 KB Expected double, but "Time" found
2 Halted 0 ms 0 KB -
# Verdict Execution time Memory Grader output
1 Incorrect 771 ms 62020 KB Expected double, but "Time" found
2 Halted 0 ms 0 KB -