poj2777

这个题是个线段树的练手题,想当年调试这个题的时候调得要吐血了。。

当年总结出来的经验是:随时随地释放标记。但是当年的标记有个很大的bug,就是我只是释放标记,没有更新线段树。因此每次访问一个节点时还得看看是否有标记没有释放。这几天为了写coci2011 sequence,我只好重新开始写线段树。今天突然想到,释放标记时更新线段树,那么query就可以直接取值了,而modify则只需push一遍。push也简单了很多,两个赋值足以,代码量瞬间精简。


#include <stdio.h>
#ifndef ONLINE_JUDGE
#include <memory.h>
#endif

#define maxn 131072

int st[maxn * 2];
int mark[maxn * 2];

inline void push(int t, int m)
{
  mark[t] = st[t] = m;
}

inline void clear(int t)
{
  static int i;
  int bak = t, find = 0;
  for (; t; t >>= 1)
    if (mark[t])
      find = t;
  if (!find) return;
  i = mark[find], mark[find] = 0, st[bak] = i;
  for (; bak != find; bak >>= 1)
    push (bak ^ 1, i), st[bak] = i, mark[bak] = 0;
}

int query(int l, int r)
{
  int ans = 0;
  for (clear(l += maxn - 1), clear(r += maxn + 1); l ^ r ^ 1; l >>= 1, r >>= 1)
    {
      if (~l & 1) ans |= st[l ^ 1];
      if ( r & 1) ans |= st[r ^ 1];
    }
  return ans;
}

int modify(int l, int r, int c)
{
  c = 1 << c;
  for (clear(l += maxn - 1), clear(r += maxn + 1); l ^ r ^ 1; l >>= 1, r >>= 1)
    {
      if (~l & 1) push (l ^ 1, c);
      if ( r & 1) push (r ^ 1, c);
      st[l >> 1] = st[l ^ 1] | st[l], st[r >> 1] = st[r ^ 1] | st[r];
    }
  for (l >>= 1; l; l >>= 1)
    st[l] = st[l << 1] | st[l << 1 | 1];
}

int main()
{
#ifndef ONLINE_JUDGE
  freopen("2777.in" , "r", stdin);
  freopen("2777.out", "w", stdout);
#endif
  int l, t, o, a, b;
  char cmd[5];

  scanf("%d%d%d", &l, &t, &o);
  for (a = l + maxn; a; --a)
    st[a] = 2;
  for (; o; --o)
    {
      scanf("%s%d%d", cmd, &a, &b);
      if (a > b)
        t = a, a = b, b = t;
      if (cmd[0] == 'C')
        scanf("%d", &t), modify(a, b, t);
      else
        printf("%d\n", __builtin_popcount(query(a, b)));
    }
    
  return 0;
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值