首页 > 代码库 > poj 2777 Counting Colors

poj 2777 Counting Colors

单线段树单记录的套路,记录的是这个区间一致的颜色或者0

技巧是这个颜色可以用1 << (color - 1)来表示,这样结果就是所有收集的颜色取或运算,数一数有多少个1就行了。

这个一致性体现在以下合并与分割时的过程,分割只需要把一致颜色放下去(为0就不放了),合并时只有两侧区间颜色一致才记录

#define tree_merge       tree_obj = tree[root<<1] == tree[root<<1|1] ? tree[root << 1] : 0
#define tree_split       decl_mid; if(tree_obj){tree[root<<1]=tree[root<<1|1] = tree_obj; tree_obj = 0;}


#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
#define FRAME       tree_frame
#define eq(x, y)    (!strcmp((x), (y)))
#define times(n, i)    for(int i=0; i<n; ++i)
#define range(a, b, i) for(int i=a; i<b; ++i)
/* --globals */

int a[2050000];
int M, N, T;
int tree[8050000];
#define tree_frame       int l = 1, int r = N + 1, int root = 1
#define tree_obj         (tree[root])
#define tree_merge       tree_obj = tree[root<<1] == tree[root<<1|1] ? tree[root << 1] : 0
#define tree_split       decl_mid; if(tree_obj){tree[root<<1]=tree[root<<1|1] = tree_obj; tree_obj = 0;}
#define TAG_INSIDE       (l >= sl && r <= sr)
#define TAG_OUTSIDE      (l >= sr || r <= sl)
#define TAG_LEAF         (l == r-1)
#define decl_mid         int mid = (l + r) / 2;
#define recur_left       l, mid, root << 1
#define recur_right      mid, r, root << 1 | 1
void build(FRAME){
  if(TAG_LEAF){ tree_obj = 1; return; }
  tree_split;
  build(recur_left); build(recur_right);
  tree_merge;  
}	

void update(int value, int sl, int sr, FRAME){
//printf("%d %d %d %d %d %d\n", value, sl, sr, l, r, root);
  if(TAG_INSIDE) { 
    tree_obj = 1 << (value - 1);
    return ;
  }
  if(TAG_OUTSIDE){ return; }
  tree_split;
  update(value, sl, sr, recur_left ); 
  update(value, sl, sr, recur_right);
  tree_merge;
}

int result;
void query_impl(int sl, int sr, FRAME){
  if(TAG_INSIDE){ 
	  if(tree_obj != 0){
	     result |= tree_obj; 
	     return; 
	  }
  }
  if(TAG_OUTSIDE){ return; }
  tree_split;
  query_impl(sl, sr, recur_left);
  query_impl(sl, sr, recur_right);
  tree_merge;
}

int query(int sl, int sr){
  result = 0;
  query_impl(sl, sr);  
  int ans = 0;
 // printf("%x\n", result);
  while(result > 0) ans += result & 1, result >>= 1;
  return ans;
}


	
int main(){
     scanf("%d%d%d", &N, &T, &M);
     build();
     while(M--){
	int a, b, c;
	char tmp[1024];
	scanf("%s%d%d", tmp, &a, &b);
	if(a > b) std::swap(a, b);
	if(eq(tmp, "C")) {
  	  scanf("%d", &c);
	  update(c, a, b+1);
	}
	if(eq(tmp, "P")){
	  printf("%d\n", query(a, b+1));
	}
     }
  return 0;
}


poj 2777 Counting Colors