POJ 2777 线段树

错误原因:
1. 没有分析清楚什么时候需要向上或者先下传递颜色
2.又把seg[root].l 和 x 搞混淆了
 
思路:采用线段树来处理,节点的成员c用来记录颜色,采用位运算来处理,有30种颜色,二进制位从右往左数第k位表示有无颜色,那么可以用与运算 |  来合并颜色;成员same表示节点所表示区间颜色是否一样,加入same后可以在log(n)时间内实现线段树的insert和query操作。insert时要注意如果区间颜色一样,那么左右子树的颜色也一样,要在insert时传递下去
 
 
 
  1. /*
  2. PROG:
  3. LANG: C++
  4. ID: heben991
  5. */
  6. // algorihm:
  7. #include <iostream>
  8. #include <algorithm>
  9. #include <vector>
  10. #include <string>
  11. #include <cctype>
  12. #include <queue>
  13. /*
  14. #include <list>
  15. #include <stack>
  16. #include <set>
  17. #include <map>
  18. #include <cmath>
  19. */
  20. using namespace std;
  21. #define ma(a,b) (a)>(b)?(a):(b)
  22. #define mi(a,b) (a)<(b)?(a):(b)
  23. #define FF(i,a,b) for(int i=(a);i<=(b);i++)
  24. #define RR(i,b) for(int i=(0);i<(b);i++)
  25. #define clr(x) memset(x,0,sizeof(x))
  26. #define pb push_back
  27. #define mp make_pair
  28. #define sz size()
  29. #define F  first
  30. #define S  second
  31. #define vv vector
  32. #define ii iterator
  33. /*
  34. #include <sstream>
  35. #include <iterator>
  36. #define ssm stringstream
  37. */
  38. #define cn continue
  39. #define br break
  40. typedef int type;
  41. const int ST = 0;
  42. #define out(x) cout << #x << "=" << x << endl
  43. template <class T> void show(T a, int n) { for (int i = ST; i < ST+n; i++) { cout<<a[i]<<' '; } cout<<endl; }
  44. template <class T> void show(T a, int r, int l) { for (int i = ST; i < ST+r; i++) show(a[i], l); cout<<endl; }
  45. const int N=110000,M=100000;
  46. struct node
  47. {
  48.  int l,r,c;
  49.  bool same;
  50. };
  51. node seg[4*N];
  52. int l, t, o;
  53. void build(int root, int x, int y)
  54. {
  55.  int len=y-x+1;
  56.  int mid=(x+y)/2;
  57.  seg[root] = (node) { x,y,1,1};
  58.  if(len>1)
  59.  {
  60.   build(root*2,x,mid);
  61.   build(root*2+1,mid+1,y);
  62.  }
  63. }
  64. void insert(int root, int x, int y, int color)
  65. {
  66.  int mid=(seg[root].l+seg[root].r)/2;
  67.  if(x<=seg[root].l && y>=seg[root].r)
  68.  {
  69.   seg[root].c = 1<<(color-1);
  70.   seg[root].same = 1;
  71.  }
  72.  else
  73.  {
  74.   if(seg[root].same)
  75.   {
  76.    seg[root*2].same = seg[root*2+1].same = 1;
  77.    seg[root*2].c = seg[root*2+1].c = seg[root].c;
  78.   }
  79.   if(x<=mid)insert(root*2,x,y,color);
  80.   if(y>mid)insert(root*2+1,x,y,color);
  81.   seg[root].c = seg[root*2].c | seg[root*2+1].c;
  82.   seg[root].same = 0;
  83.  }
  84. }
  85. /*
  86. 10 5 8
  87. C 1 9 2
  88. C 3 8 3
  89. P 1 10
  90. 2
  91. */
  92. int query(int root, int x, int y)
  93. {
  94.  int mid=(seg[root].r+seg[root].l)/2;
  95.  if(seg[root].same)return seg[root].c;
  96.  if(x<=seg[root].l && y>=seg[root].r)
  97.  {
  98.   return seg[root].c;
  99.  }
  100.  {
  101.   int ls=0,rs=0;
  102.   if(x<=mid)ls = query(root*2,x,y);
  103.   if(y>mid)rs = query(root*2+1,x,y);
  104.   return ls | rs;
  105.  }
  106. }
  107. int count(int x)
  108. {
  109.  int ret=0;
  110.  //printf("%x ", x);
  111.  while(x>0)
  112.  {
  113.   ret += x & 1;
  114.   x>>=1;
  115.  }
  116.  //printf("%d/n", ret);
  117.  return ret;
  118. }
  119. int main()
  120. {
  121.  char s[10];
  122.  int a, b, c;
  123.  scanf("%d%d%d", &l, &t, &o);
  124.  //printf("%d %d %d/n", l, t, o);
  125.  build(1,1,M);
  126.  while(o--)
  127.  {
  128.   scanf("%s%d%d", s, &a, &b);
  129.   //printf("%s %d %d/n", s, a, b);
  130.   if(a>b) swap(a,b);
  131.   if(s[0]=='C')
  132.   {
  133.    scanf("%d", &c);
  134.    insert(1,a,b,c);
  135.   }
  136.   else
  137.   {
  138.    printf("%d/n", count(query(1,a,b)));
  139.   }
  140.  }
  141.     return 0;
  142. }
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值