1. 程式人生 > >POJ-2892/HDU-1540 Tunnel Warfare (樹狀陣列+二分查詢)

POJ-2892/HDU-1540 Tunnel Warfare (樹狀陣列+二分查詢)

這兩道題的題目時一樣的,但是資料不一樣。

bool d[maxn]; 用於記錄村莊i是否被炸燬

建立一個樹狀陣列bit[maxn],sum(i)用於計算[1,i]區間內被摧毀的村莊的個數

stack<int> 記錄被炸燬的村莊的順序

下面對三種指令進行處理

首先對資料做一點說明:POJ的資料中應該沒有繼續炸燬已經被炸燬村莊的操作,但是HDU的資料中有

1. D x   摧毀x村莊 對於POJ 的資料,直接壓棧,修改標記,維護樹狀陣列,完事

                               對於HDU的資料,需要壓棧,然後判斷標記,如果為假,即村莊此時尚未被炸燬那就修改標記,維護樹狀陣列

                               如果為真,即村莊已經是被炸燬的,就不進行壓棧外的其他操作

2. R 從棧中取出最近一個被炸燬的村莊  對於poj資料來說,直接取棧頂元素;對於hdu,則需先將棧頂的標記為假元素出棧,處理                                                                    第一個標記為真的元素。操作是彈棧,修改標記維護樹狀陣列

3.Q x 如果x標記為真,輸出0;

          x標記為假,計算v=sum(x),bs(x,n+1,v+1)得到sum(i)為v+1,的第一個i,也正因為如果sum(x)就是當前的最大值,需要              設定n+1為終點;bs(0,t,v)這裡起點設定為0 是為了統一操作。二者的差就是sum(i)==v的所有i的數量,再減去第一個                sum(i)==v處的村莊被炸燬(v==0已經特殊處理),就是x能聯絡到的村莊數

POJ版本程式

#include<cstdio> 
#include<cstring>
#include<stack>
#define maxn 50005
using namespace std;
bool d[maxn];
int bit[maxn],n,m;
stack<int> s;
inline int lowbit(int i)
{
	return i&-i;
}
int sum(int x)
{
	int s=0;
	for(int i=x;i;i-=lowbit(i)) s+=bit[i];
	return s;
}
void add(int x,int v)
{
	for(int i=x;i<=n;i+=lowbit(i))
		bit[i]+=v;
}
int bs(int l,int r,int v)
{
	int mid;
	while(l<r)
	{
		mid=(l+r)/2;
		if(sum(mid)>=v) r=mid;
		else l=mid+1;
	}
	return l;
}
int main()
{
	char q[10]; int t;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		memset(bit+1,0,sizeof(int)*n);
		memset(d+1,0,sizeof(bool)*n);
		while(!s.empty()) s.pop();
		for(int i=0;i<m;i++)
		{
			scanf("%s",q);
			if(q[0]=='D')
			{
				scanf("%d",&t);
				d[t]=true;
				s.push(t);
				add(t,1);
			}
			else if(q[0]=='R')
			{
				d[s.top()]=false;
				add(s.top(),-1);
				s.pop();
			}
			else
			{
				scanf("%d",&t);
				if(d[t]) printf("0\n");
				else 
				{
					int v=sum(t);
					printf("%d\n",bs(t,n+1,v+1)-bs(0,t,v)-1);
				}
			}
		}
	}
	return 0;
}

HDU版本程式

#include<cstdio> 
#include<cstring>
#include<stack>
#define maxn 50005
using namespace std;
bool d[maxn];
int bit[maxn],n,m;
stack<int> s;
inline int lowbit(int i)
{
	return i&-i;
}
int sum(int x)
{
	int s=0;
	for(int i=x;i;i-=lowbit(i)) s+=bit[i];
	return s;
}
void add(int x,int v)
{
	for(int i=x;i<=n;i+=lowbit(i))
		bit[i]+=v;
}
int bs(int l,int r,int v)
{
	int mid;
	while(l<r)
	{
		mid=(l+r)/2;
		if(sum(mid)>=v) r=mid;
		else l=mid+1;
	}
	return l;
}
int main()
{
	char q[10]; int t;
	while(scanf("%d%d",&n,&m)!=EOF)
	{
		memset(bit+1,0,sizeof(int)*n);
		memset(d+1,0,sizeof(bool)*n);
		while(!s.empty()) s.pop();
		for(int i=0;i<m;i++)
		{
			scanf("%s",q);
			if(q[0]=='D')
			{
				scanf("%d",&t);
				s.push(t);
				if(!d[t])
				{
					d[t]=true;
					add(t,1);
				}
			}
			else if(q[0]=='R')
			{
				while(!d[s.top()]) s.pop();
				d[s.top()]=false;
				add(s.top(),-1);
				s.pop();
			}
			else
			{
				scanf("%d",&t);
				if(d[t]) printf("0\n");
				else 
				{
					int v=sum(t);
					printf("%d\n",bs(t,n+1,v+1)-bs(0,t,v)-1);
				}
			}
		}
	}
	return 0;
}