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