这两道题的题目时一样的,但是数据不一样。
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;
}