7 9 D 3 D 6 D 5 Q 4 Q 5 R Q 4 R Q 4
1 0 2 4
要记录单元被损坏的顺序,用一个栈就好了,毁坏就入栈,修复就出栈
说说思路,最难的是查询一个点附近有那些的连接着的区间
这需要在线段树记录三个信息,tlen,llen,rlen,这个记录和 poj 3667 Hotel 记录的意义是相同的 , tlen表示该节点内最长的可用区间的长度,llen表示最左端数起的区间长度,rlen表示从最右端数起的区间长度
对于一个点,看它是在当前区间的左半还是右半
在左半的话,看看是不是在右端的连续区间内,是的话,还要加上右半区间的左端连续区间。否则的话,只要计算它在左半区间的连接情况即可
在右半的话同理,看看是不是在左端的连续区间内,是的话,还要加上左半区间的右端连续区间。否则的话,只要计算它在右半区间的连接情况即可
所以需要时刻维护好每个节点的tlen,llen,rlen,在updata函数中,和 poj 3667 Hotel 的维护是一样的
看代码:#include <stdio.h>
#define MAX 150100
struct Seg{
int l,r;
int ls,rs,ms ; //分别是记录从左端点起连续的区间数目, 从右端点起连续的区间数目,区间内最大的连续区间 数目
}st[MAX];
int s[MAX/3] , top = 0; //模拟栈
void creat(int l , int r ,int pos)
{
st[pos].l = l ,st[pos].r = r ;
st[pos].ls = st[pos].rs = st[pos].ms = r-l+1 ;
if(l == r)
{
return ;
}
int mid = (l+r)>>1 ;
creat(l,mid,pos<<1) ;
creat(mid+1,r,pos<<1|1) ;
}
int max(int a , int b)
{
return a>b?a:b ;
}
void insert(int t , int flag , int pos)
{
if(st[pos].l == st[pos].r)
{
if(flag == 1)
{
st[pos].ls = st[pos].rs = st[pos].ms = 1 ; //修复
}
else
{
st[pos].ls = st[pos].rs = st[pos].ms = 0 ; //毁坏
}
return ;
}
int mid = (st[pos].l+st[pos].r)>>1 ;
if(t<=mid) insert(t,flag,pos<<1) ;
else insert(t,flag,pos<<1|1) ;
st[pos].ls = st[pos<<1].ls;
st[pos].rs = st[pos<<1|1].rs ;
if(st[pos<<1].ls == st[pos<<1].r-st[pos<<1].l+1)
{
st[pos].ls += st[pos<<1|1].ls ;
}
if(st[pos<<1|1].rs == st[pos<<1|1].r-st[pos<<1|1].l+1)
{
st[pos].rs += st[pos<<1].rs ;
}
//父亲区间内的最大区间必定是,左子树最大区间,右子树最大区间,左右子树合并的中间区间,三者中最大的区间值
st[pos].ms = max(max(st[pos<<1].ms,st[pos<<1|1].ms),st[pos<<1].rs+st[pos<<1|1].ls) ;
}
int query(int t , int pos)
{
if(st[pos].l == st[pos].r || st[pos].ms == 0 || st[pos].ms == st[pos].r-st[pos].l+1)
{
return st[pos].ms ;
}
int mid = (st[pos].l+st[pos].r)>>1 ;
if(t<=mid)
{
//下面的请注意
if(t >= st[pos<<1].r-st[pos<<1].rs+1)//因为t<=mid,看左子树,st[POS<<1].r-st[POS<<1].rs+1代表左子树右边连续区间的左边界值,如果t在左子树的右区间内,则要看右子树的左区间有多长并返回
{
return query(t,pos<<1)+query(mid+1,pos<<1|1) ;
}
else
{
return query(t,pos<<1) ;
}
}
else
{
if(t <= st[pos<<1|1].l+st[pos<<1|1].ls-1)
{
return query(mid,pos<<1)+query(t,pos<<1|1) ;
}
else
{
return query(t,pos<<1|1) ;
}
}
}
int main()
{
int n , m;
while(~scanf("%d%d",&n,&m))
{
char flag[3];
int t;
creat(1,n,1) ;
top = 0 ;
for(int i = 0 ;i < m ; ++i)
{
scanf("%s",flag) ;
if(flag[0] == 'D')
{
scanf("%d",&t) ;
insert(t,0,1) ;
s[top++] = t ;
}
else if(flag[0] == 'Q')
{
scanf("%d",&t) ;
printf("%d\n",query(t,1));
}
else
{
if(top>=0)
{
insert(s[--top],1,1) ;
}
}
}
}
return 0 ;
}hdu 1540 Tunnel Warfare 一个关于线段的故事~~~线段树是我无法言明的伤~
原文:http://blog.csdn.net/lionel_d/article/details/44626521