Tunnel Warfare
题意:D t摧毁村庄t,R 重建最后一个摧毁的村庄, Q t查询与t村庄连接的村庄个数。
思路:线段树维护连续子区间,将未被破坏的村庄看成1,破坏的看成0,线段树维护3个信息,前缀最长1序列,后缀最长1序列,最长1序列。
#include<bits/stdc++.h>
using namespace std;
struct node{
int l,r,len;
}a[200005];
int ql,qr;
void build(int o,int l,int r){
a[o].l=a[o].r=a[o].len=r-l+1;
if(l==r)
return;
int m=(l+r)>>1;
build(o*2,l,m);
build(o*2+1,m+1,r);
}
void up(int o,int l,int r){
if(l==r){
a[o].len=a[o].l=a[o].r=ql;
return;
}
int m=(l+r)>>1;
if(m>=qr)
up(o*2,l,m);
else
up(o*2+1,m+1,r);
a[o].len=max(a[o*2].r+a[o*2+1].l,max(a[o*2].len,a[o*2+1].len));
a[o].l=a[o*2].l;
a[o].r=a[o*2+1].r;
if(a[o*2].l==m-l+1)
a[o].l+=a[o*2+1].l;
if(a[o*2+1].r==r-m)
a[o].r+=a[o*2].r;
}
int qu(int o,int l,int r,int pos){
if(a[o].len==0||l==r||a[o].len==r-l+1)
return a[o].len;
int m=(l+r)>>1;
if(m>=pos){
if(pos>m-a[o*2].r)
return qu(o*2,l,m,pos)+qu(o*2+1,m+1,r,m+1);
else return qu(o*2,l,m,pos);
}
else{
if(pos<m+1+a[o*2+1].l)
return qu(o*2,l,m,m)+qu(o*2+1,m+1,r,pos);
else return qu(o*2+1,m+1,r,pos);
}
}
int main(){
int n,m;
while(~scanf("%d%d",&n,&m)){
stack<int>s;
char c[10];
int t;
build(1,1,n);
while(m--){
scanf("%s",c);
if(c[0]=='D'){
scanf("%d",&t);
s.push(t);
ql=0,qr=t;
up(1,1,n);
}
else if(c[0]=='R'){
ql=1;
qr=s.top();
s.pop();
up(1,1,n);
}
else{
scanf("%d",&t);
printf("%d\n",qu(1,1,n,t));
}
}
}
return 0;
}