During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally speaking, villages connected by tunnels lay in a line. Except the two at the ends, every village was directly connected with two neighboring ones.
Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!
Frequently the invaders launched attack on some of the villages and destroyed the parts of tunnels in them. The Eighth Route Army commanders requested the latest connection state of the tunnels and villages. If some villages are severely isolated, restoration of connection must be done immediately!
There are three different events described in different format shown below:
D x: The x-th village was destroyed.
Q x: The Army commands requested the number of villages that x-th village was directly or indirectly connected with including itself.
R: The village destroyed last was rebuilt.
7 9 D 3 D 6 D 5 Q 4 Q 5 R Q 4 R Q 4
1 0 2 4
类似的题目之前没有做过,想了很久没想出来,看的题解后A的。这道题需要引进从区间左边向右边延展的可行域(ll),从右边向左延展的可行域(rr),区间的最大可行域(data)。
如果我们要查询,那么从最大的区间折半查询,问题是如何确定区间的取舍问题。其实存在着如下关系。
假设我们要查询的点为t。
分别对t进行讨论,如果t在左子树并且在左子树的rr之内,就要查询一下左子树,右子树。如果不在就只是查询左子树。
t在右子树内同理
还有一个问题,就是在需要查询相邻子树的时候查询点如何选取。如果这个条件成立,我们就要去选择相邻子树的端点。为什么?因为只有端点值是最可靠的(自行思考)。
通过做这道题,还是觉得关系都是从最基础找起。比如更新ll,rr,其实在叶子节点ll,rr的值已经是可以确定的,当叶子节点为1时,ll=rr=data=1,当叶子节点为0时,
ll=rr=data=0。然后就是向上去更新,上边的区间rr是右子树的rr,ll是左子树的ll。当然,子树满的情况分别讨论。
#include<bits/stdc++.h>
using namespace std;
const int M=5e4+10;
struct aa
{
int ll,rr,data;
} tree[4*M];
int save[M],stc[M];
void creat(int now,int l,int r)
{
tree[now].ll=tree[now].rr=tree[now].data=r-l+1;
if(l==r)
return ;
int mid=(r+l)/2;
creat(now*2+1,l,mid);
creat(now*2+2,mid+1,r);
}
void update(int now,int l,int r,int t,int w)
{
if(l==r)
{
tree[now].ll=tree[now].rr=tree[now].data=w;
return ;
}
int mid=(l+r)/2;
if(t<=mid)
{
update(now*2+1,l,mid,t,w);
}
else
{
update(now*2+2,mid+1,r,t,w);
}
tree[now].ll=tree[now*2+1].ll;
tree[now].rr=tree[now*2+2].rr;
tree[now].data=max(max(tree[now*2+1].data,tree[now*2+2].data),tree[now*2+1].rr+tree[now*2+2].ll);
if(tree[now*2+1].ll==mid-l+1)
{
tree[now].ll+=tree[now*2+2].ll;
}
if(tree[now*2+2].ll==r-mid)
{
tree[now].rr+=tree[now*2+1].rr;
}
}
int query(int now,int l,int r,int t)
{
if(l==r||tree[now].data==0||tree[now].data==r-l+1)
return tree[now].data;
int mid=(l+r)/2;
if(t<=mid)
{
if(t>=mid-tree[now*2+1].rr+1)
{
return query(now*2+1,l,mid,t)+query(now*2+2,mid+1,r,mid+1);
}
else
{
return query(now*2+1,l,mid,t);
}
}
else
{
if(t<=mid+tree[now*2+2].ll)
{
return query(now*2+1,l,mid,mid)+query(now*2+2,mid+1,r,t);
}
else
{
return query(now*2+2,mid+1,r,t);
}
}
}
int main()
{
int n,m;
while(scanf("%d%d",&n,&m)!=EOF)
{
int top=0;
creat(0,0,n-1);
getchar();
while(m--)
{
char tempchar;
int tempint;
scanf("%c",&tempchar);
getchar();
if(tempchar=='D')
{
scanf("%d",&tempint);
getchar();
stc[++top]=tempint;
update(0,0,n-1,tempint-1,0);
}
else if(tempchar=='Q')
{
scanf("%d",&tempint);
getchar();
printf("%d\n",query(0,0,n-1,tempint-1));
}
else
{
tempint=stc[top--];
update(0,0,n-1,tempint-1,1);
}
}
}
}