hdu 1540 线段树

题意:有n个点依次链接,先给出三种操作:
  1. 删除某个点
  2. 修复某个点
  3. 查询与某个点相连的点的个数
解法:主要是query函数的写法。利用回溯,分情况判断左/右是否联通。 注意自定义的结构一定要赋初值。
 
 
# include <iostream >
# include <string >
# include <vector >
# include <map >
# include <set >
# include <stack >
# include <queue >
# include <algorithm >
using namespace std;
# include <cstdio >
# include <cstring >
# include <cmath >
# include <cstdlib >
# define PAUSE system( "pause")
# define Pr printf
# define Sc scanf
# define pb push_back
# define Sort(v) sort(v.begin(), v.end())
# define Unique(v) (unique(v.begin(), v.end()) -v.begin())
# define MM(x, y) memset(x, y, sizeof(x))
# define For(i, s, t) for( int i =s; i <(t); i ++)
# define eps ( 1e - 9)
# define pi 3. 1415926
# define N 50005
struct Statue
{
     bool l, r;
     int len;
    Statue( int len = 0, bool l = false, bool r = false) : len(len), l(l), r(r){}
};
struct SegmentTreeNode
{
     bool ok;
}tree[N << 2];
int used[N];
void build( int l, int r, int p)
{
    tree[p].ok = true;
     if(l == r)
         return;
     int m = (l +r) >> 1;
    build(l, m, p << 1);
    build(m + 1, r, p << 1 | 1);
}
void updata( int l, int r, int p, int k, bool ok)
{
     if(l == r)
    {
        tree[p].ok = ok;
         return ;
    }
     int m = (l +r) >> 1;
     if(k < = m)
        updata(l, m, p << 1, k, ok);
     else
        updata(m + 1, r, p << 1 | 1, k, ok);
    tree[p].ok = tree[p << 1].ok && tree[p << 1 | 1].ok;
}
Statue query( int l, int r, int p, int k)
{
     if(tree[p].ok == true)
    {
         return Statue(r -l + 1, true, true);
    }
     if(l == r)
    {
         return Statue( 0, false, false);
    }
     int m = (l +r) >> 1;
    Statue s1, s2;//忘记给s1, s2赋初值,蛋疼了好久。
     if(k < = m)
    {
        s1 = query(l, m, p << 1, k);
         if(s1.r == true)
            s2 = query(m + 1, r, p << 1 | 1, m + 1);
         return Statue(s1.len +s2.len, s1.l, s2.r);
    }
     else
    {
        s2 = query(m + 1, r, p << 1 | 1, k);
         if(s2.l == true)
            s1 = query(l, m, p << 1, m);
         return Statue(s1.len +s2.len, s1.l, s2.r);
    }
}
int n, m;
int main()
{
     while(Sc( "%d%d", &n, &m) != EOF)
    {
        stack < int > vec;
        MM(used, 0);
        build( 1, n, 1);
        For(i, 0, m)
        {
             static char ch;
             static int x;
            Sc( " %c", &ch);
             if(ch == 'R')
            {
                 while( !used[vec.top()] )
                    vec.pop();
                updata( 1, n, 1, vec.top(), true);
                used[vec.top()] = 0;
                vec.pop();
            }
             else
            {
                Sc( "%d", &x);
                 if(ch == 'D')
                {
                    vec.push(x);
                    used[x] ++;
                    updata( 1, n, 1, vec.top(), false);
                }
                 else
                {
                    Statue s = query( 1, n, 1, x);
                    Pr( "%d\n", s.len);
                }
            }
        }
    }
     return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值