6
11
2016
0

【bzoj4551】【Tjoi2016&Heoi2016】【线段树维护dfs序】树

//Ryan ___与孤独为伴,同清醒共舞.
int n,m;
int timer=0,st[N],ed[N],dep[N]; 
void dfs(int x,int ff)
{
	st[x]=++timer;
	dep[x]=dep[ff]+1;//根节点深度为1 
	R(i,x){
		int y=e[i].go;
		if(y==ff) continue;
		dfs(y,x);
	}
	ed[x]=timer;
}

#define lson k<<1,l,mid
#define rson k<<1|1,mid+1,r
struct seg{int l,r,tag;}t[N<<2];
void build(int k,int l,int r)
{
	t[k].l=l;t[k].r=r;t[k].tag=1;
//	if(l==r){t[k].v=1;return;}
	if(l==r) return;
	int mid=l+r>>1;
	build(lson);build(rson);
}
int better(int x,int y){return dep[x]<dep[y]?y:x;}
void modify(int k,int lx,int rx,int val)//区间取max 
{
	int l=t[k].l,r=t[k].r;
	if(lx<=l&&r<=rx) t[k].tag=better(t[k].tag,val);//注意包含关系 
	else{
		int mid=l+r>>1;//t[k].l t[k].r
		if(lx<=mid) modify(k<<1,lx,rx,val);
		if(rx>mid) modify(k<<1|1,lx,rx,val);
	}
}
int query(int k,int pos)//单点查询 
{
	int l=t[k].l,r=t[k].r;
	if(l==r) return t[k].tag;
	int mid=l+r>>1,ans=t[k].tag;
	if(pos<=mid) return better(ans,query(k<<1,pos));
	else return better(ans,query(k<<1|1,pos));
}

int main()
{
//	freopen("tree.txt","r",stdin);
	n=read();m=read();
	F(i,1,n-1){
		int x=read(),y=read();
		addedge(x,y);
	}
	dfs(1,0);
	build(1,1,n);
	while(m--){
		char op[5];int x;
		scanf("%s",op);x=read();
		if(op[0]=='C') modify(1,st[x],ed[x],x);
		else if(op[0]=='Q') printf("%d\n",query(1,st[x]));
	}
	return 0;
}

题意:给定一棵n个节点的数,要求资瓷m个操作,操作有两种:

1. 对某个结点打上标记

2. 询问某个结点最近的一个打了标记的祖先

n,m<=10^5

 

Category: 树套树 | Tags: | Read Count: 367

登录 *


loading captcha image...
(输入验证码)
or Ctrl+Enter

Host by is-Programmer.com | Power by Chito 1.3.3 beta | Theme: Aeros 2.0 by TheBuckmaker.com