码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 1540 Tunnel Warfare(区间合并)【线段树】

时间:2018-09-24 00:38:20      阅读:174      评论:0      收藏:0      [点我收藏+]

标签:tunnel   main   build   模拟   scan   oid   string   tar   类型   

<题目链接>

题目大意:

题意:一个长度为n的线段,下面m个操作

D x 表示将单元x毁掉

R  表示修复最后毁坏的那个单元

Q x  询问这个单元以及它周围有多少个连续的单元,如果它本身已经被毁坏了就是0。

解题分析:

用线段树求指定点所在的最长连续区间,属于线段树区间合并类型的题,线段树的每个节点需要维护三个值,分别是对应区间的最长连续区间长度,对应区间最长连续区间前缀,对应区间最长连续后缀,然后就是在每次update之后都维护一下这三个值就行。并且注意一下query 时的操作。

 

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 using namespace std;
 5 
 6 #define Lson rt<<1,l,mid
 7 #define Rson rt<<1|1,mid+1,r
 8 const int N=50000+4;
 9 int len[N<<2],llen[N<<2],rlen[N<<2];
10 int n,m;
11 
12 void Pushup(int rt,int length){    //更新维护每个节点的三个值
13     llen[rt]=llen[rt<<1];   //首先当前节点的最长连续前缀==左子节点的最长连续前缀     
14     rlen[rt]=rlen[rt<<1|1];
15     /*-- 进一步更新 --*/   
16     if(llen[rt<<1]==(length-(length>>1)))llen[rt]+=llen[rt<<1|1]; //如果左子节点的最长连续前缀为整个左子区间,那么本节点的前缀还要加上右子区间的最长前缀
17     if(rlen[rt<<1|1]==(length>>1))rlen[rt]+=rlen[rt<<1];          //同理
18     /*-- 最终更新本节点的最长连续长度  --*/
19     len[rt]=max(max(len[rt<<1],len[rt<<1|1]),rlen[rt<<1]+llen[rt<<1|1]); 
20 }
21 
22 void build(int rt,int l,int r){
23     if(l==r){
24         len[rt]=llen[rt]=rlen[rt]=1;
25         return;
26     }
27     int mid=(l+r)>>1;
28     build(Lson);
29     build(Rson);
30     Pushup(rt,r-l+1);
31 }
32 
33 void update(int rt,int l,int r,int loc,int c){   //单点更新
34     if(l==r){
35         len[rt]=llen[rt]=rlen[rt]=c; 
36         return;
37     }
38     int mid=(l+r)>>1;
39     if(loc<=mid)update(Lson,loc,c);
40     if(loc>mid)update(Rson,loc,c);
41     Pushup(rt,r-l+1);
42 }
43 
44 int query(int rt,int l,int r,int loc){
45     if(l==r)return len[rt];
46     int mid=(l+r)>>1;
47     if(loc<=mid){
48         if(loc+rlen[rt<<1]>mid)return rlen[rt<<1]+llen[rt<<1|1]; //如果loc在左子区间的最长后缀和右子区间的最长前缀中,直接输出这两个前后缀之和即可
49         else return query(Lson,loc);  //否则的话,继续向左子节点查询
50     }
51     else{
52         if(mid+llen[rt<<1|1]>=loc)return rlen[rt<<1]+llen[rt<<1|1];//如果loc在左子区间的最长后缀和右子区间的最长前缀中,直接输出这两个前后缀之和即可
53         else return query(Rson,loc);
54     }
55 }
56 
57 int main(){
58     while(scanf("%d %d",&n,&m)!=EOF){
59         build(1,1,n);
60         int tot=0,stk[N+10]; //stk模拟栈
61         while(m--){
62             char str[10];
63             scanf("%s",str);
64             if(str[0]==D){
65                 int cal;scanf("%d",&cal);
66                 stk[++tot]=cal;
67                 update(1,1,n,cal,0);
68             }
69             else if(str[0]==R){
70                 int cal=stk[tot--];
71                 update(1,1,n,cal,1);
72             }
73             else{
74                 int cal;scanf("%d",&cal);
75                 printf("%d\n",query(1,1,n,cal));
76             }
77         }
78     }
79     return 0;
80 }

 

 

2018-09-23

HDU 1540 Tunnel Warfare(区间合并)【线段树】

标签:tunnel   main   build   模拟   scan   oid   string   tar   类型   

原文地址:https://www.cnblogs.com/00isok/p/9693880.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!