您的位置:首页 > 其它

POJ 2892 Tunnel Warfare || HDU 1540(树状数组+二分 || 线段树的单点更新+区间查询)

2014-02-24 21:00 627 查看
点我看题目

题意 :N个村子连成一条线,相邻的村子都有直接的地道进行相连,不相连的都由地道间接相连,三个命令,D x,表示x村庄被摧毁,R ,表示最后被摧毁的村庄已经重建了,Q x表示,与x直接或间接相连的村庄有多少个,当然包括他自己。

思路 :这是一道用线段树,树状数组,还有STL都可以做的题。。。。因为用线段树的更新什么的太麻烦,。。。。。所以我用了树状数组

//1540
#include <cstdio>
#include <cstring>
#include <iostream>

using namespace std ;

int lz[51000*4],p[51000 * 4],vis[51000 * 4],stk[51000*4] ;

void pushup(int rt)
{
p[rt] = p[rt << 1] + p[rt << 1 | 1] ;
}
void update(int x,int l,int r,int rt,int sc)
{
if(l == r)
{
p[rt] = sc ;
return ;
}
int mid = (l+r) >> 1 ;
if(x <= mid)
update(x,l,mid,rt << 1 , sc) ;
else
update(x,mid+1,r,rt << 1 | 1 ,  sc) ;
pushup(rt) ;
}
int query(int L,int R,int l,int r,int rt)
{
int sum = 0 ;
if(L <= l && r <= R)
{
return p[rt] ;
}
int mid = (l+r) >> 1 ;
if(mid >= L)
sum += query(L,R,l,mid,rt << 1) ;
if(mid < R)
sum += query(L,R,mid+1,r,rt << 1 | 1) ;
return sum ;
}
int findd(int l,int r,int x,int rt)
{
if(l == r)
{
return l;
}
int mid = (l+r) >> 1 ;
if(x <= p[rt << 1])
return findd(l,mid,x,rt << 1) ;
else return findd(mid+1,r,x-p[rt << 1],rt << 1 | 1) ;
}
int main()
{
int n, m,x;
char ch[3] ;
while(~scanf("%d %d",&n,&m))
{
int top = 0 ;
memset(p,0,sizeof(p)) ;
memset(vis,0,sizeof(vis)) ;
for(int i = 0 ; i < m ; i++)
{
scanf("%s",ch)  ;
if(ch[0] == 'R')
{
if(top != 0)
{
vis[stk[top-1]] = 0 ;//村庄存在即为0,被摧毁即为1
update(stk[top-1],1,n,1,0) ;
top-- ;
}
}
else if(ch[0] == 'D')
{
scanf("%d",&x) ;
vis[x] = 1 ;
stk[top++] = x ;
update(x,1,n,1,1) ;
}
else if(ch[0] == 'Q')
{
scanf("%d",&x) ;
if(vis[x])
{
printf("0\n") ;
continue ;
}
int l,r ;
int l1 = query(1,x,1,n,1) ;//x村庄左边的和
if(l1 == 0)//如果和为0,说明x村庄左边全部都存在
l = 1 ;
else l = findd(1,n,l1,1)+1;//找出左边离x最近的那个一,既不存在的那个村庄
int r1 = query(x,n,1,n,1) ;
if(r1 == 0)
r = n;
else r = findd(1,n,l1+1,1)-1 ;
printf("%d\n",r-l+1) ;
}
}
}
return 0 ;
}


View Code
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: 
相关文章推荐