您的位置:首页 > 其它

BZOJ1103 [POI2007]大都市meg(DFS序)

2015-10-13 11:03 429 查看
题目:一颗树,单边修改,链上查询。。实际上链是根到结点的链。网上好像有其他做法,我的想法是这样的:

先不看修改,毫无疑问查询只是查询结点的深度;而修改一条边会有什么影响:影响是且只是以边上深度最深结点为根的子树。

所以就是DFS序了。把子树转化为区间,然后用区间修改、单点查询的线段树维护。

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
#define MAXN 255555
struct Edge{
int v,nxt;
}edge[MAXN];
int n,NE,head[MAXN];
void addEdge(int u,int v){
edge[NE].v=v; edge[NE].nxt=head[u]; head[u]=NE++;
}

int dep[MAXN],l[MAXN],r[MAXN],stack[MAXN],odr;
void dfs(){
int top=0;
stack[++top]=1;
while(top){
int u=stack[top];
if(l[u]){
r[u]=odr; --top;
continue;
}
l[u]=++odr;
for(int i=head[u]; i!=-1; i=edge[i].nxt){
int v=edge[i].v;
stack[++top]=v;
dep[v]=dep[u]+1;
}
}
}

int tree[MAXN<<2],N,x,y;
void update(int i,int j,int k){
if(x<=i&&j<=y){
++tree[k];
return;
}
if(tree[k]){
tree[k<<1]+=tree[k]; tree[k<<1|1]+=tree[k];
tree[k]=0;
}
int mid=i+j>>1;
if(x<=mid) update(i,mid,k<<1);
if(y>mid) update(mid+1,j,k<<1|1);
}
int query(int i,int j,int k){
if(i==j) return tree[k];
if(tree[k]){
tree[k<<1]+=tree[k]; tree[k<<1|1]+=tree[k];
tree[k]=0;
}
int mid=i+j>>1;
if(x<=mid) return query(i,mid,k<<1);
return query(mid+1,j,k<<1|1);
}

int main(){
int m,a,b;
char op[11];
memset(head,-1,sizeof(head));
scanf("%d",&n);
for(int i=1; i<n; ++i){
scanf("%d%d",&a,&b);
if(a>b) swap(a,b);
addEdge(a,b);
}
dfs();
for(N=1; N<odr; N<<=1);
scanf("%d",&m);
m+=n-1;
while(m--){
scanf("%s",op);
if(op[0]=='W'){
scanf("%d",&a);
x=l[a];
printf("%d\n",dep[a]-query(1,N,1));
}else{
scanf("%d%d",&a,&b);
if(a<b) a=b;
x=l[a]; y=r[a];
update(1,N,1);
}
}
return 0;
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: