HDU 1540 Tunnel Warfare(区间合并)线段树
Posted 00isok
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了HDU 1540 Tunnel Warfare(区间合并)线段树相关的知识,希望对你有一定的参考价值。
<题目链接>
题目大意:
题意:一个长度为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 ",query(1,1,n,cal)); 76 } 77 } 78 } 79 return 0; 80 }
2018-09-23
以上是关于HDU 1540 Tunnel Warfare(区间合并)线段树的主要内容,如果未能解决你的问题,请参考以下文章
HDU1540 Tunnel Warfare —— 线段树 区间合并
hdu1540 Tunnel Warfare 线段树/树状数组