hdu1540-Tunnel Warfare-(线段树+二分)
Posted shoulinniao
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了hdu1540-Tunnel Warfare-(线段树+二分)相关的知识,希望对你有一定的参考价值。
题意:有n个村庄排成一列,相邻的村庄可以通信,炸毁则不可以通信,进行m个操作。3种操作,1.炸毁某村庄;2.修复上一个被炸毁的村庄;3.查询某个村庄能通信的村庄数(自己算一个)。
解题:求某个点左边扩散和右边扩散的区间和,没被炸毁就算1,炸毁则算0,用二分查找左边界和右边界,假设查询的点为x,则左边界是x-l+1=query(),右边界判断标准是r-x+1=query();两次二分log,查询query也是log,时间复杂度是O(n+m*log*log),限速2000ms,1600+ms,思路简单,勉强能过。
另外还有一个坑:一个村庄可以被多次炸毁,修复只需要一次就够了。
1 #include<stdio.h> 2 #include<iostream> 3 #include<algorithm> 4 #include<cstring> 5 #include<math.h> 6 #include<string> 7 #include<map> 8 #include<queue> 9 #include<stack> 10 #include<set> 11 #define ll long long 12 #define inf 0x3f3f3f3f 13 using namespace std; 14 15 int n,m; 16 int a[50005]; 17 int sum[50005*4]; 18 stack<int>sta; 19 20 void build(int l,int r,int rt) 21 22 if(l==r) 23 24 sum[rt]=a[l]; 25 return; 26 27 int mid=(l+r)/2; 28 build(l,mid,rt*2); 29 build(mid+1,r,rt*2+1); 30 31 sum[rt]=sum[rt*2]+sum[rt*2+1]; 32 33 34 void update(int p,int c,int l,int r,int rt) 35 36 if(l==r)///到达叶节点,修改后返回 37 38 sum[rt]=sum[rt]+c; 39 return ; 40 41 int mid=(l+r)/2; 42 ///根据条件判断往左调用还是往右 43 if(p<=mid) update(p,c,l, mid, rt*2); 44 else update(p,c,mid+1, r, rt*2+1); 45 sum[rt] = sum[rt*2] + sum[rt*2+1]; 46 47 48 int query(int L,int R,int l,int r,int rt) 49 50 if(L<=l&&r<=R)///在区间内,直接返回 51 return sum[rt]; 52 53 int m=(l+r)/2; 54 55 ///累计答案 56 int ans=0; 57 if(L<=m) ans=ans+query(L,R,l,m,rt*2); 58 if(R>m) ans=ans+query(L,R,m+1,r,rt*2+1); 59 60 return ans; 61 62 63 int main() 64 65 while(scanf("%d%d",&n,&m)!=EOF) 66 67 while(!sta.empty()) 68 sta.pop(); 69 set<int>se; 70 for(int i=1;i<=n;i++) 71 a[i]=1; 72 build(1,n,1); 73 char c; 74 while(m--) 75 76 getchar(); 77 scanf("%c",&c); 78 int x; 79 if(c==‘D‘) 80 81 scanf("%d",&x); 82 if(a[x]!=0) 83 update(x,-1,1,n,1); 84 a[x]=0; 85 sta.push(x); 86 87 else if(c==‘R‘) 88 89 x=sta.top(); 90 if( a[x]==0 ); 91 else 92 93 while( a[x]!=0 ) 94 95 sta.pop(); 96 x = sta.top(); 97 98 99 sta.pop(); 100 a[x]=1; 101 update(x,1,1,n,1); 102 103 else 104 105 int ans=0; 106 scanf("%d",&x); 107 108 if(a[x]!=0) 109 110 int l=1,r=x,res1=-1,res2=-1; 111 while(l<=r)///往左找最大连通的村庄数 112 113 int mid=(l+r)/2; 114 if( query(mid,x,1,n,1)==x-mid+1 )///二分内往左找mid 115 116 res1=mid; 117 r=mid-1; 118 119 120 else///二分内往右找 121 122 l=mid+1; 123 124 125 l=x,r=n; 126 while(l<=r) 127 128 int mid=(l+r)/2; 129 130 if( query(x,mid,1,n,1)==mid-x+1 ) 131 132 res2=mid; 133 l=mid+1; 134 135 else 136 r=mid-1; 137 138 printf("%d\n",res2-res1+1); 139 140 else 141 printf("0\n"); 142 143 144 145 146 147 return 0; 148 149 /** 150 5 12 151 D 3 152 D 2 153 D 1 154 D 1 155 D 2 156 R 157 R 158 R 159 Q 1 160 Q 2 161 Q 3 162 Q 4 163 */
以上是关于hdu1540-Tunnel Warfare-(线段树+二分)的主要内容,如果未能解决你的问题,请参考以下文章
hdu1540 Tunnel Warfare 线段树/树状数组
hdu--1540 Tunnel Warfare(线段树+区间合并)
HDU 1540 Tunnel Warfare(线段树,单点更新,区间查询)