Cod sursa(job #2691498)

Utilizator GrizzyProblemSolver79cNot telling GrizzyProblemSolver79c Data 28 decembrie 2020 23:38:43
Problema Hotel Scor 10
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 3.8 kb
#include <bits/stdc++.h>

using namespace std;

ifstream in("hotel.in");
ofstream out("hotel.out");

int const NMAX = 1e5;

struct NodeInfo {
  //lazy flag fields
  bool lazySet0;
  bool lazySet1;

  //actual information fields
  int maxConsZeros;
  int maxZerosAtStart;
  int maxZerosAtEnd;

  void initEmpty(int node, int left, int right) {
    lazySet0 = false;
    lazySet1 = false;
    maxConsZeros = right - left + 1;
    maxZerosAtStart = right - left + 1;
    maxZerosAtEnd = right - left + 1;
  }

  void initFull(int node, int left, int right) {
    lazySet0 = false;
    lazySet1 = false;
    maxConsZeros = 0;
    maxZerosAtStart = 0;
    maxZerosAtEnd = 0;
  }
};

NodeInfo seg[1 + 8 * NMAX];

//COMMENT: make sure at one point you clean the mess (or push it outside the tree)
//We are assuming that through our model a node cannot be at the same time lazily set to 0 and lazily to to 1.
void cleanNode(int node, int left, int right) {
  if(seg[node].lazySet0 == true) {
    seg[node].initEmpty(node, left, right);
    seg[2*node].lazySet0 = true;
    seg[2*node+1].lazySet0 = true;
  } else if(seg[node].lazySet1 == true) {
    seg[node].initFull(node, left, right);
    seg[2*node].lazySet1 = true;
    seg[2*node+1].lazySet1 = true;
  }
}

//Here is going back up the tree after an update => we are working with real info
//The node is clean and his children are clean
void computeNode(int node, int left, int right) {
  int mid = (left + right)/2;

  cleanNode(2*node, left, mid);
  cleanNode(2*node + 1, mid+1, right);

  NodeInfo &son1 = seg[2*node];
  NodeInfo &son2 = seg[2*node+1];

  int size1 = mid - left + 1;
  int size2 = right - (mid+1) + 1;

  int maxZeros = max(son1.maxConsZeros, son2.maxConsZeros);
  seg[node].maxConsZeros = max(maxZeros, son1.maxZerosAtEnd + son2.maxZerosAtStart);

  seg[node].maxZerosAtStart = son1.maxZerosAtStart;
  if(son1.maxZerosAtStart == size1) {
    seg[node].maxZerosAtStart += son2.maxZerosAtStart;
  }

  seg[node].maxZerosAtEnd = son2.maxZerosAtEnd;
  if(son2.maxZerosAtEnd == size2) {
    seg[node].maxZerosAtEnd += son1.maxZerosAtEnd;
  }
  //cout << "(" << node << " " << seg[node].maxConsZeros << ")" << "\n";
}

//PREVIOUSLY, update(int node, int left, int right, int pos, int value)
void update(int node, int left, int right, int from, int to, bool val) {
  //cout << "(" << node << ", " << left << ", " << right << ") " << "[" << from << ", " << to << "] " << val << "\n";
  cleanNode(node, left, right);
  int mid = (left + right)/2;
  if(left == from && right == to) {
    if(val == 0) {
      seg[node].initEmpty(node, left, right);
      seg[2*node].lazySet0 = seg[2*node+1].lazySet0 = true;
    } else {
      seg[node].initFull(node, left, right);
      seg[2*node].lazySet1 = seg[2*node+1].lazySet1 = true;
    }
  } else {
    if(from <= mid) {
      update(2*node, left, mid, from, min(mid, to), val);
    }
    if(mid+1 <= to) {
      update(2*node + 1, mid+1, right, max(mid+1, from), to, val);
    }
    computeNode(node, left, right);
  }
}

//No point in being lazy
void build(int node, int left, int right) {
  seg[node].initEmpty(node, left, right);
  if(left != right) {
    int mid = (left + right)/2;
    build(2*node, left, mid);
    build(2*node + 1, mid+1, right);
  }
}

//in this problem updating from zero/initial state does not work, because initial zero/state has some specific modeling needed.
int main() {
  int n, p;
  in >> n >> p;
  build(1, 1, n);
  for(int i = 1; i <= p; i++) {
    int c, k1, k2;
    in >> c;
    if(c == 1) {
      in >> k1 >> k2;
      update(1, 1, n, k1, k1+k2-1, 1);
    } else if(c == 2) {
      in >> k1 >> k2;
      update(1, 1, n, k1, k1+k2-1, 0);
    } else {
      out << seg[1].maxConsZeros << "\n";
    }
  }
  return 0;
}