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;
}