美文网首页
HDU1540(Tunnel Warfare )

HDU1540(Tunnel Warfare )

作者: kimoyami | 来源:发表于2018-10-12 11:40 被阅读7次

链接:https://vjudge.net/problem/HDU-1540
思路:这个题真的想透我感觉能明白线段树很多本质,首先我们要思考区间合并信息时我们需要什么,因为是左区间的右端点和右区间的左端点进行合并,所以我们需要记录左区间的最大长度和右区间的最大长度,再维护一个当前区间的最大长度用于求合并的最大长度(合并后的最大长度可能是左右区间中某一个不含端点的区间),合并的时候注意判断。因为是单点更新,我们考虑直接更新到叶节点,查询的时候我们考虑对于需要查询的点,往左右两个区间转移,如果在左子树且在右区间范围,那么结果就是左子树的右区间长度+右子树的左区间长度,如果在左子树但是不在其右区间范围内,那么查询左子树,如果在右子树同理可推(在这里wa了两个小时,我直接查询的左右区间,这样当查询点不在当前区间内也会有返回值)。

#include<cstdio>
#include<algorithm>
#include<cstring>
#include<stack>
using namespace std;

const int maxn = 1e5+10;
int sum[maxn<<2],ll[maxn<<2],rr[maxn<<2];
int n,q;

inline void pushup(int o,int m){//判断各种合并情况
    if(ll[o<<1]==(m-(m>>1)))ll[o] = ll[o<<1] + ll[o<<1|1];
    else ll[o] = ll[o<<1];
    if(rr[o<<1|1]==(m>>1))rr[o] = rr[o<<1|1] + rr[o<<1];
    else rr[o] = rr[o<<1|1];
    sum[o] = max(max(sum[o<<1],sum[o<<1|1]),rr[o<<1]+ll[o<<1|1]);
}

void build(int o,int l,int r){
  if(l<r){
    int mid = l+r>>1;
    build(o<<1,l,mid);
    build(o<<1|1,mid+1,r);
    pushup(o,r-l+1);
  }
  else{
    sum[o] = 1;
    ll[o] = 1;
    rr[o] = 1;
  }
}

void destroy(int o,int tl,int tr,int v){
    if(v<tl||v>tr)return;
  if(tl==tr){
      ll[o] = 0;
      rr[o] = 0;
      sum[o] = 0;
      return ;
  }
  int mid = (tl+tr)>>1;
  destroy(o<<1,tl,mid,v);
  destroy(o<<1|1,mid+1,tr,v);
  pushup(o,tr-tl+1);
} 

void rebuild(int o,int tl,int tr,int v){
     if(v<tl||v>tr)return;
    if(tl==tr){
      ll[o] = 1;
      rr[o] = 1;
      sum[o] = 1;
      return ;
  }
  int mid = (tl+tr)>>1;
  rebuild(o<<1,tl,mid,v);
  rebuild(o<<1|1,mid+1,tr,v);
  pushup(o,tr-tl+1);
}

int query(int o,int tl,int tr,int v){
  if(sum[o]==tr-tl+1||sum[o]==0||tr==tl)return sum[o];
  int mid = (tl+tr)>>1;
  if(v<=mid){
      if(v>=mid-rr[o<<1]+1)return rr[o<<1]+ll[o<<1|1];
      else return query(o<<1,tl,mid,v);
  }
  else{
      if(v<=mid+ll[o<<1|1])return rr[o<<1]+ll[o<<1|1];
      else return query(o<<1|1,mid+1,tr,v);
  }
}

stack<int> s;
char ch[10];

int main(){ 
    while(~scanf("%d%d",&n,&q)){
        while(!s.empty())s.pop();
        memset(sum,0,sizeof(sum));
        memset(ll,0,sizeof(ll));
        memset(rr,0,sizeof(rr));
        build(1,1,n);
    for(int i=0;i<q;i++){
        int o;
        scanf("%s",ch);
        if(ch[0]=='D'){
            scanf("%d",&o);
            destroy(1,1,n,o);
            s.push(o);
        }
        if(ch[0]=='R'){
            if(!s.empty()){
            int p = s.top();
            s.pop();
            rebuild(1,1,n,p);
            }
        }
        if(ch[0]=='Q'){
            scanf("%d",&o);
            printf("%d\n",query(1,1,n,o));
        }
    }
    }
    return  0;
}

相关文章

网友评论

      本文标题:HDU1540(Tunnel Warfare )

      本文链接:https://www.haomeiwen.com/subject/fpmwaftx.html