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

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

时间:2017-10-04 23:58:29      阅读:509      评论:0      收藏:0      [点我收藏+]

标签:logs   ack   合并   ==   stream   href   ios   print   线段   

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=1540

题意:n个村子,相邻两个村子初始都是联通的,询问经过一些操作后村子x最多和几个村子联通(包括村子x)。

操作的话有破坏(破坏相当于村子消失)和修复(修复是以栈的形式顺序)

题解:

  1 //HDU 1540 Tunnel Warfare
  2 //线段树 区间合并
  3 #include <stack>
  4 #include <cstdio>
  5 #include <iostream>
  6 #include <algorithm>
  7 using namespace std;
  8 
  9 typedef long long LL;
 10 const int N=50000+10;
 11 
 12 struct Tree
 13 {
 14     LL l,r;
 15     LL prelen,nextlen,maxlen;
 16     //左端最大连续区间,右端最大连续区间,区间内最大连续区间
 17 };
 18 Tree tree[4*N];
 19 
 20 void pushup(LL x) //向上更新 
 21 {
 22     LL tmp=x<<1;
 23     tree[x].prelen=tree[tmp].prelen;
 24     tree[x].nextlen=tree[tmp+1].nextlen;
 25     tree[x].maxlen=max(tree[tmp].maxlen,tree[tmp+1].maxlen);
 26     tree[x].maxlen=max(tree[x].maxlen,tree[tmp].nextlen+tree[tmp+1].prelen);
 27     //最大区间为左右儿子的最大区间和(左儿子的右端最大区间+右儿子的左端最大区间)中的最大值
 28     //左 中 右 选择问题
 29     
 30     if(tree[tmp].prelen==tree[tmp].r-tree[tmp].l+1) //左儿子左端区间满值,父亲加上右儿子的左端区间 
 31     tree[x].prelen+=tree[tmp+1].prelen;
 32     
 33     if(tree[tmp+1].nextlen==tree[tmp+1].r-tree[tmp+1].l+1) //右儿子右区间满值,父亲加上左儿子的右端区间 
 34     tree[x].nextlen+=tree[tmp].nextlen;
 35 }
 36 
 37 void build(LL l,LL r,LL x)
 38 {
 39     tree[x].l=l;
 40     tree[x].r=r;
 41     tree[x].maxlen=tree[x].prelen=tree[x].nextlen=r-l+1;
 42     if(l==r) return ;
 43     LL tmp=x<<1;
 44     LL mid=(l+r)>>1;
 45     build(l,mid,tmp);
 46     build(mid+1,r,tmp+1);
 47 }
 48 
 49 void update(LL k,LL c,LL x)
 50 {
 51     if(k<tree[x].l||k>tree[x].r) return ;
 52     if(tree[x].l==k&&tree[x].r==k)
 53     {
 54         tree[x].maxlen=tree[x].prelen=tree[x].nextlen=c;
 55         return ;    
 56     }
 57     LL tmp=x<<1;
 58     LL mid=(tree[x].l+tree[x].r)>>1;
 59     if(k<=mid) update(k,c,tmp);
 60     else update(k,c,tmp+1);
 61     pushup(x);
 62 }
 63 
 64 LL query(LL k,LL x)
 65 {
 66     if(tree[x].l==tree[x].r||tree[x].maxlen==tree[x].r-tree[x].l+1||tree[x].maxlen==0){
 67         return tree[x].maxlen;
 68     } //询问到满值或者0或者叶子节点就必要继续往下找 
 69     LL tmp=x<<1;
 70     LL mid=(tree[x].l+tree[x].r)>>1;
 71     if(k<=mid){ //寻找的点在左儿子的右端区域,很可能可以连接右儿子,所以还要在右儿子那边找下 
 72         if(k>=tree[tmp].r-tree[tmp].nextlen+1) return query(k,tmp)+query(mid+1,tmp+1);
 73         else return query(k,tmp); //否则直接在左儿子的左端区域找 
 74     }
 75     else{ //同理(滑稽.jpg) 
 76         if(k<=tree[tmp+1].l+tree[tmp+1].prelen-1) return query(mid,tmp)+query(k,tmp+1);
 77         else return query(k,tmp+1);
 78     }
 79 }
 80 
 81 int main(){
 82     LL n,m,A;
 83     char op[2];
 84     while(scanf("%lld%lld",&n,&m)!=EOF){
 85         stack <LL> S;
 86         build(1,n,1);
 87         for(int i=1;i<=m;i++){
 88             scanf("%s",op);
 89             if(op[0]==D){
 90                 scanf("%lld",&A);
 91                 S.push(A);
 92                 update(A,0,1);
 93             }
 94             else if(op[0]==Q){
 95                 scanf("%lld",&A);
 96                 printf("%lld\n",query(A,1));
 97             }
 98             else if(op[0]==R){
 99                 if(!S.empty()){
100                     A=S.top();S.pop();
101                     update(A,1,1);
102                 }
103             }
104         }
105     }
106     return 0;
107 }

 

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

标签:logs   ack   合并   ==   stream   href   ios   print   线段   

原文地址:http://www.cnblogs.com/Leonard-/p/7627813.html

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