poj2892 Tunnel Warfare(数状数组+二分)

原题地址:点击打开链接

题意:有1-n个村子,D- x表示摧毁x村,R表示修好刚被摧毁的村子,Q-x,表示询问你x所在的村子附近一共有多少村子是没有摧毁的。

思路:这种询问的题型一般直接都会想到用树状数组做,我们可以用树状数组记录被摧毁的村子的和,p[x],表示1-x共有多少村子被摧毁,

然后我们可以用二分查找进行解答,当你询问x村时,如果x村已经被摧毁,那就输出0,否则先找出1-x村有多少被摧毁,假设n个被摧毁,这个时候我们就可以用

二分查找,找出x最小为多少时有n个村子被摧毁,x最大为多少时有多少村子被摧毁,答案就是 xMax-xMin.

树状数组详解:点击打开链接

#include<stdio.h>
#include<string.h>
using namespace std;
int p[50010],n;
int lowbit(int i)
{
	return i&(-i);
}
void add(int i,int x)
{
	while(i<=n)
	{
		p[i]+=x;
		i+=lowbit(i);
	}
}
int sum(int i)
{
	int res=0;
	while(i>=1)
	{
		res+=p[i];
		i-=lowbit(i);
	}
	return res;
}
int binary_search(int x)
{
	int left=0,right=n+1;
	while(left<right)
	{
		int mid=(left+right)/2;
		if(sum(mid)>=x)
		{
			right=mid;
		}
		else
		{
			left=mid+1;
		}
	}
	return right;
}
int main()
{
	int i,m,x,d[50010],cnt;
	bool mark[50010];
	char str[10];
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		cnt=0;
		memset(p,0,sizeof(p));
		memset(mark,false,sizeof(mark));
		for(i=0;i<m;i++)
		{
			scanf("%s",str);
			if(str[0]=='D')
			{
				scanf("%d",&x);
				add(x,1);
				mark[x]=true;
				d[cnt++]=x;
			}
			else if(str[0]=='R')
			{
				x=d[--cnt];
				add(x,-1);
				mark[x]=false;
			}
			else
			{
				scanf("%d",&x);
				if(mark[x]==true)
				{
					printf("0\n");
					continue;
				}
				x=sum(x);
				int a=binary_search(x);
				int b=binary_search(x+1);
				int res=b-a-1;
				printf("%d\n",res);
			}
		}
	}
	return 0;
} 


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值