题意:n个村子连成一排。之间可以互相通信。但是可能有些村子被破坏,就会阻隔通信联系。然后这些被破坏的村子能够被修复,且修复的是最近被破坏的村子。给几次询问,问与x通信联系的村子有几个,包括x自己。
思路:我是直接用栈模拟,线段树也可以做。
poj能过。hdu过不了:
#include<cstdio>
#include<stack>
#include<cstring>
using namespace std;
const int maxn = 5*1e5+100;
int de[maxn];
int main()
{
int n,m;
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
while(~scanf("%d%d",&n,&m))
{
memset(de,0,sizeof(de));
stack<int> s;
while(m--)
{
char op[5];
int x;
scanf("%s%d",op);
if(op[0]=='R')
{
if(!s.empty())
{
de[s.top()]=0;
s.pop();
}
}
else if(op[0]=='D')
{
de[x]=1;
s.push(x);
}
else if(op[0]=='Q')
{
if(de[x])printf("0\n");
else
{
int rp=0;
for(int i=x;i<=n&&!de[i];i++)
rp++;
for(int i=x-1;i>=1&&!de[i];i--)
rp++;
printf("%d\n",rp);
}
}
}
}
}
线段树
#include<cstdio>
#include<stack>
#include<algorithm>
using namespace std;
const int maxn = 51000;
struct SegTree
{
int l,r;
int ll,rr,mm;//分别记录从区间左右开始的最大连续段,及整个区间的最大连续段
}node[maxn*3];
void build(int root,int l,int r)
{
node[root].l=l;
node[root].r=r;
node[root].ll=r-l+1;
node[root].rr=r-l+1;
node[root].mm=r-l+1;
if(l==r)
return;
int mid=(l+r)>>1;
build(2*root,l,mid);
build(2*root+1,mid+1,r);
}
void update(int i,int x,int t)
{
if(node[i].l==node[i].r)
{
if(t==0)
node[i].ll=node[i].rr=node[i].mm=0;
else
node[i].ll=node[i].rr=node[i].mm=1;
return;
}
int mid=(node[i].l+node[i].r)>>1;
if(x>mid)
update(2*i+1,x,t);
else if(x<=mid)
update(2*i,x,t);
node[i].ll=node[i*2].ll;
node[i].rr=node[i*2+1].rr;
node[i].mm=max(node[i*2].mm,node[i*2+1].mm);//不考虑中间拼接
node[i].mm=max(node[i].mm,node[i*2].rr+node[i*2+1].ll);//中间拼接
if(node[i*2].ll==node[i*2].r-node[i*2].l+1)node[i].ll+=node[i*2+1].ll;//跨过了左区间
if(node[i*2+1].rr==node[i*2+1].r-node[i*2+1].l+1)node[i].rr+=node[i*2].rr;
}
int query(int i,int x)
{
if(node[i].l==node[i].r||node[i].mm==0||node[i].mm==node[i].r-node[i].l+1)
return node[i].mm;
int mid=(node[i].l+node[i].r)>>1;
if(x<=mid)
{
if(x>=node[i*2].r-node[i*2].rr+1)//左子区间 的被炸毁点右侧,仍要合并右子区间信息
return query(i*2,x)+query(i*2+1,mid+1);
else
return query(i*2,x);
}
else
{
if(x<=node[i*2+1].l+node[i*2+1].ll-1)
return query(i*2,mid)+query(i*2+1,x);
else
return query(i*2+1,x);
}
}
int main()
{
int n,m;
// freopen("in.txt","r",stdin);
while(~scanf("%d%d",&n,&m))
{
char op[100];
stack<int> s;
build(1,1,n);
while(m--)
{
scanf("%s",op);
int x;
if(op[0]=='D')
{
scanf("%d",&x);
s.push(x);
update(1,x,0);
}
else if(op[0]=='R')
{
int x=s.top();s.pop();
update(1,x,1);
}
else
{
scanf("%d",&x);
printf("%d\n",query(1,x));
}
}
}
}