1. 程式人生 > >HDU 1540 Tunnel Warfare(線段樹 區間合並)

HDU 1540 Tunnel Warfare(線段樹 區間合並)

tle def ons main logs tmp 區間合並 http 合並

題目鏈接: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(線段樹 區間合並)