D. Beard Graph

https://codeforces.com/problemset/problem/165/D

主要是边转点

后面都是简单的线段树维护

我们维护ok标记,val值,黑(1),白(0) 

id.ok=l.ok&r.ok

id.val=l.val+r.val

注意特判如果两个点一样是0,如果dfn[u]+1>dfn[v]就不用询问了直接返回

code

// Problem: Beard Graph
// Contest: Luogu
// URL: https://www.luogu.com.cn/problem/CF165D
// Memory Limit: 250 MB
// Time Limit: 4000 ms
// 
// Powered by CP Editor (https://cpeditor.org)

#include<iostream>
#include<vector>
using namespace std;
const int N=1e5+9;
int n;
int a[N];
struct edge{
	int u,v,w;
}ee[N];
vector<edge> e[N];
void add(int u,int v){
	e[u].push_back({v,u,1});
	e[v].push_back({u,v,1});
}
int sz[N],fa[N],wc[N],dep[N],dis[N];
void dfs1(int u,int f){
	fa[u]=f;
	sz[u]=1;
	dep[u]=dep[f]+1;
	for(auto &[x,y,z] : e[u]){
		if(x==f){
			dis[u]=z;
			continue;
		}
		if(x!=f){
			dfs1(x,u);
			sz[u]+=sz[x];
			if(sz[x]>sz[wc[u]]){
				wc[u]=x;
			}
		}
	}
}
int top[N],dfn[N],vistime;
void dfs2(int u,int Top){
	dfn[u]=++vistime;
	a[vistime]=dis[u];
	top[u]=Top;
	if(wc[u]){
		dfs2(wc[u],Top);
		for(auto &[x,y,z] : e[u]){
			if(x!=wc[u] && x!=fa[u]){
				dfs2(x,x);
			}
		}
	}
}
//线段树
struct SEG{
    #define INF (1<<31)
    #define ll long long
    #define tl(id) (id<<1)
    #define tr(id) (id<<1|1)
    #define li inline
    struct node{
    	int l,r;
    	int ok;
        ll val;
    }seg[N<<2];
    void pushup(node &id,node &l,node &r){
    	id.ok=l.ok&r.ok;
    	id.val=l.val+r.val;
    }
    void pushup(int id){
    	pushup(seg[id],seg[tl(id)],seg[tr(id)]);
    }
    li int inrange(int L,int R,int l,int r){return l<=L && R<=r;}
    li int outofrange(int L,int R,int l,int r){return L>r || R<l;}
    li void build(const int id,int l,int r){
    	seg[id]={l,r};
        if(l==r){
            seg[id].val=a[l];
            seg[id].ok=a[l];
            return;
        }
        int mid=(l+r)>>1;
        build(tl(id),l,mid);
        build(tr(id),mid+1,r);
        pushup(id);
    }
    li void update(int id,int l,int r,int pos,int v){
    	if(l==r){
    		seg[id].val=v;
    		seg[id].ok=v;
    		return;
    	}
		int mid=(l+r)>>1;
		if(mid>=pos){
			update(tl(id),l,mid,pos,v);
		}else{
			update(tr(id),mid+1,r,pos,v);
		}
		pushup(id);
    }
    li node query(int id,int l,int r){
    	if(seg[id].l>=l && seg[id].r<=r){
    		return seg[id];
    	}else{
    		int mid=(seg[id].l+seg[id].r)>>1;
    		if(mid>=r){
    			return query(tl(id),l,r);
    		}else if(mid<l){
    			return query(tr(id),l,r);
    		}else{
    			node res;
    			node left=query(tl(id),l,r);
    			node right=query(tr(id),l,r);
    			pushup(res,left,right);
    			return res;
    		}
    	}
    }
}t;
#define node SEG::node
ll ask(int u,int v){
	ll res=0;
	while(top[u]!=top[v]){
		if(dep[top[u]]<dep[top[v]]){
			swap(u,v);
		}
		node tt=t.query(1,dfn[top[u]],dfn[u]);
		if(!tt.ok){
			return -1;
		}else{
			res+=tt.val;
		}
		u=fa[top[u]];
	}
	if(dfn[u]>dfn[v]){
		swap(u,v);
	}
	if(dfn[u]+1>dfn[v]){
		return res;
	}
	node tt=t.query(1,dfn[u]+1,dfn[v]);
	if(!tt.ok){
		return -1;
	}else{
		res+=tt.val;
	}
	return res;
}
int main(){
	cin>>n;
	for(int i=1;i<=n-1;i++){
		int u,v;
		cin>>u>>v;
		ee[i]={u,v,1};
		add(u,v);
	}
	dfs1(1,0);
	dfs2(1,1);
	t.build(1,1,n);
	int m;
	cin>>m;
	for(int i=1;i<=m;i++){
		int op;
		cin>>op;
		if(op==1){
			int u;
			cin>>u;
			if(dep[ee[u].u]>dep[ee[u].v]){
				u=ee[u].u;
			}else{
				u=ee[u].v;
			}
			t.update(1,1,n,dfn[u],1);
		}else if(op==2){
			int u;
			cin>>u;
			if(dep[ee[u].u]>dep[ee[u].v]){
				u=ee[u].u;
			}else{
				u=ee[u].v;
			}
			t.update(1,1,n,dfn[u],0);
		}else{
			int u,v;
			cin>>u>>v;
			if(u==v){
				cout<<0<<'\n';
			}else{
				cout<<ask(u,v)<<'\n';
			}
		}
	}
	return 0;
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值