poj2892--Tunnel Warfare(线段树)

题目链接:点击打开链接

题目大意:给出n个格子,三种操作,D k:消除第k个格子,R:恢复最后一次消除的格子,Q k:问和k相连的最长连续序列。

求最长连续序列,线段树统计每段中被消除的最大点和最小点,更新点k,查询段[1,k][k,n],然后相减得到结果

#include <cstdio>
#include <cstring>
#include <stack>
#include <algorithm>
using namespace std ;
#define INF 0x3f3f3f3f
int cl_max[500000] , cl_min[500000] ;
stack <int> sta ;
void push_up(int rt) {
    cl_max[rt] = max(cl_max[rt<<1],cl_max[rt<<1|1]) ;
    cl_min[rt] = min(cl_min[rt<<1],cl_min[rt<<1|1]) ;
}
void update(int k,int flag,int l,int r,int rt) {
    if(l == r) {
        if( flag == -1 )
            cl_max[rt] = 0 , cl_min[rt] = INF ;
        else
            cl_max[rt] = cl_min[rt] = k ;
        return ;
    }
    if( k <= (l+r)/2 )
        update(k,flag,l,(l+r)/2,rt<<1) ;
    else
        update(k,flag,(l+r)/2+1,r,rt<<1|1) ;
    push_up(rt) ;
}
int query1(int ll,int rr,int l,int r,int rt) {
    if( rr < l || ll > r ) return 0 ;
    if( ll <= l && rr >= r ) return cl_max[rt] ;
    return max(query1(ll,rr,l,(l+r)/2,rt<<1),query1(ll,rr,(l+r)/2+1,r,rt<<1|1)) ;
}
int query2(int ll,int rr,int l,int r,int rt) {
    if( rr < l || ll > r ) return INF ;
    if( ll <= l && rr >= r ) return cl_min[rt] ;
    return min(query2(ll,rr,l,(l+r)/2,rt<<1),query2(ll,rr,(l+r)/2+1,r,rt<<1|1)) ;
}
int main() {
    int n , m , k , min1 , max1 ;
    char s[5] ;
    while( scanf("%d %d", &n, &m) !=EOF ) {
        memset(cl_max,0,sizeof(cl_max)) ;
        memset(cl_min,INF,sizeof(cl_min)) ;
        while( !sta.empty() ) sta.pop() ;
        while( m-- ) {
            scanf("%s", s) ;
            if( s[0] == 'D' ) {
                scanf("%d", &k) ;
                sta.push(k) ;
                update(k,1,1,n,1) ;
            }
            else if( s[0] == 'Q' ) {
                scanf("%d", &k) ;
                max1 = query1(1,k,1,n,1) ;
                min1 = query2(k,n,1,n,1) ;
                //printf("Q--> max1 = %d min1 = %d\n", max1 , min1) ;
                if( min1 == INF ) min1 = n+1 ;
                if( max1 == min1 )
                    printf("0\n") ;
                else
                    printf("%d\n", min1-1-max1 ) ;
            }
            else{
                k = sta.top() ;
                sta.pop() ;
                update(k,-1,1,n,1) ;
            }
        }
    }
    return 0 ;
}


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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值