HDU 6183 Color it

线段树。

假设只有一种颜色,因为每次询问有一个$x$一定是$1$,那么我可以想办法找出每一个$y$最小的$x$是多少,如果最小的都不符合,那么一定不符合,因为更新变成了单点更新,询问是区间询问最小值,搞个线段树即可。有$51$种颜色,可以搞$51$个线段树。

#include <bits/stdc++.h>
using namespace std;

const int maxn = 6000000 + 10;
int op;
int root[60];
struct Node {
  int val;
  int L;
  int R;
}s[maxn];
int num;

int add() {
  num ++;
  s[num].val = 2000000;
  s[num].L = -1;
  s[num].R = -1;
  return num;
}

void update(int rt, int pos, int val, int l, int r) {
  if(l == r) {
    s[rt].val = min(s[rt].val, val);
    return ;
  }
  int mid = (l + r) / 2;
  if(pos <= mid) {
    if(s[rt].L == -1) {
      s[rt].L = add();
    }
    update(s[rt].L, pos, val, l, mid);
  } else {
    if(s[rt].R == -1) {
      s[rt].R = add();
    }
    update(s[rt].R, pos, val, mid + 1, r);
  }
  int left = 2000000;
  int right = 2000000;
  if(s[rt].L != -1) {
    left = s[s[rt].L].val;
  }
  if(s[rt].R != -1) {
    right = s[s[rt].R].val;
  }
  s[rt].val = min(left, right);
}

int query(int rt, int L, int R, int l, int r) {
  if(L <= l && r <= R) {
    return s[rt].val;
  }
  int mid = (l + r) / 2;
  int left = 2000000;
  int right = 2000000;
  if(L <= mid && s[rt].L != -1) {
    left = query(s[rt].L, L, R, l, mid);
  }
  if(R > mid && s[rt].R != -1) {
    right = query(s[rt].R, L, R, mid + 1, r);
  }
  return min(left, right);
}

int main() {
 // freopen("D://in.txt", "r", stdin);
  while(~scanf("%d", &op)) {
    if(op == 0) {
      for(int i = 0; i <= 50; i ++) {
        root[i] = add();
      }
    } else if(op == 1) {
      int x, y, c;
      scanf("%d%d%d", &x, &y, &c);
      update(root[c], y, x, 1, 1000000);
    } else if(op == 2) {
      int x, y1, y2;
      scanf("%d%d%d", &x, &y1, &y2);
      int ans = 0;
      for(int i = 0; i <= 50; i ++) {
        if(query(root[i], y1, y2, 1, 1000000) <= x) {
          ans ++;
        }
      }
      printf("%d\n", ans);
    } else {
      break;
    }
  }
  return 0;
}

  

posted @ 2017-09-08 08:53  Fighting_Heart  阅读(283)  评论(0编辑  收藏  举报