Cod sursa(job #2273608)

Utilizator mouse_wirelessMouse Wireless mouse_wireless Data 31 octombrie 2018 19:52:11
Problema Cutii Scor 0
Compilator cpp-64 Status done
Runda Arhiva de probleme Marime 4.24 kb
#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define mp make_pair
#define CHECK(x) if(!(x)) return false;
#define CHECKRET(x, y) if(!(x)) return (y);
#define SKIP(x) if((x)) continue;
typedef pair<int, int> pii;

#ifdef INFOARENA
#define ProblemName "cutii"
#else
#define ProblemName "fis"
#endif

#define InFile ProblemName ".in"
#define OuFile ProblemName ".out"

const int MAXBUF = 30000000;
char parseBuf[MAXBUF];
char *head;
bool isDigit[255];

void parseInit() {
  int a = fread(parseBuf, 1, MAXBUF, stdin);
  parseBuf[a] = 0;
  head = parseBuf;
  memset(isDigit, 0, sizeof isDigit);
  for (int i = '0'; i <= '9'; ++i)
    isDigit[i] = true;
}

int nextInt() {
  int ans = 0;
  for (; !isDigit[(int)*head]; ++head);
  for (; isDigit[(int)*head]; ++head)
    ans = ans * 10 + (*head) - '0';
  return ans;
}

struct node {
  int key;
  int height;
  node* left;
  node* right;
  int size, val;
  int maxelem;
  void set(int k, int v) {
    key = k;
    left = right = NULL;
    height = 1;
    size = 1;
    val = v;
    maxelem = v;
  }
  node(int k, int v) {
    set(k, v);
  }
};

deque<node> nodeCache;
stack<node*> recycleBin;

node *fetchNode(int k, int val) {
  if (!recycleBin.empty()) {
    node *t = recycleBin.top();
    recycleBin.pop();
    t->set(k, val);
    return t;
  }
  nodeCache.push_back(node(k, val));
  return &nodeCache.back();
}

void destroyNode(node *n) {
  if (n == NULL) return;
  recycleBin.push(n);
  destroyNode(n->left);
  destroyNode(n->right);
}

inline int height(node* p) {
  return p ? p->height : 0;
}

inline int size(node *p) {
  return p ? p->size : 0;
}

inline int bfactor(node* p) {
  return height(p->right) - height(p->left);
}

inline int maxelem(node *p) {
  return p ? p->maxelem : 0;
}

void fixheight(node* p) {
  int hl = height(p->left);
  int hr = height(p->right);
  p->height = (hl>hr ? hl : hr) + 1;
  p->size = size(p->left) + size(p->right) + 1;
  p->maxelem = max(p->val, max(maxelem(p->left), maxelem(p->right)));
}

node* rotateright(node* p) {
  node* q = p->left;
  p->left = q->right;
  q->right = p;
  fixheight(p);
  fixheight(q);
  return q;
}

node* rotateleft(node* q) {
  node* p = q->right;
  q->right = p->left;
  p->left = q;
  fixheight(q);
  fixheight(p);
  return p;
}

node* balance(node* p) {
  fixheight(p);
  if (bfactor(p) == 2) {
    if (bfactor(p->right) < 0)
      p->right = rotateright(p->right);
    return rotateleft(p);
  }
  if (bfactor(p) == -2) {
    if (bfactor(p->left) > 0)
      p->left = rotateleft(p->left);
    return rotateright(p);
  }
  return p;
}

node* insert(node* p, int k, int val) {
  if (!p) return fetchNode(k, val);
  if (k < p->key)
    p->left = insert(p->left, k, val);
  else
    p->right = insert(p->right, k, val);
  return balance(p);
}

int tquery(node *root, int y) {
  CHECKRET(root != NULL, 0);
  if (root->key > y) return tquery(root->left, y);
  int best = 0;
  best = max(best, maxelem(root->left));
  best = max(best, root->val);
  best = max(best, tquery(root->right, y));
  return best;
}

const int MAXN = 3510;
pair<int, pii> v[MAXN];

node *AIB[MAXN];
int arbSz;

inline int zeros(int x) {
  return ((x ^ (x - 1)) & x);
}

void update(int x, int y, int val) {

  for (int i = x; i <= arbSz; i += zeros(i))
    AIB[i] = insert(AIB[i], y, val);
}

int query(int x, int y) {
  int ret = 0;

  for (int i = x; i > 0; i -= zeros(i))
    ret = max(ret, tquery(AIB[i], y));
  return ret;
}

int main() {
  assert(freopen(InFile, "r", stdin));
  assert(freopen(OuFile, "w", stdout));
  parseInit();
  int N, T;
  N = nextInt();
  T = nextInt();
  arbSz = N;

  while (T--) {
    for (int i = 1; i <= N; ++i)
      destroyNode(AIB[i]);
    for (int i = 1; i <= N; ++i) {
      v[i].first = nextInt();
      v[i].second.first = nextInt();
      v[i].second.second = nextInt();
    }
    sort(v + 1, v + N + 1);
    int best = 0;
    for (int i = 1; i <= N; ++i) {
      int rez = query(v[i].second.first - 1, v[i].second.second - 1);
      ++rez;
      best = max(best, rez);
      update(v[i].second.first, v[i].second.second, rez);
    }
    printf("%d\n", best);
  }
  return 0;
}