前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >E - Explorer

E - Explorer

作者头像
用户2965768
修改2019-08-29 09:41:25
8830
修改2019-08-29 09:41:25
举报
文章被收录于专栏:wymwym

给你 n 个点,m 条边,每条边给你一组数 (u, v, l, r) 代表如果你想从u点走到v点,你的身高需要满足范围 [ l , r ] ,问你从 1 走到 n 点,你有多少种身高可以选择。

解:先对所有的 l, r 离散化建线段树, 每个结点表示 大于等于当前点小于下一个点的 区间,比如有 1 5 两个点,线段树中就有一个结点表示区间 [1,4]。 建树如果当前边 能在该 结点表示的区间,就加入这条边。 于是对每种范围的区间 已经把所有的边加进去了。 接下来分治区间, 如果 [L,R] 区间所有的选择都行,就ans+=所有选择,

否则 就 [L,mid] 和 [mid+1,R] 考虑,由于并查集有撤销操作,不能压缩路径

代码语言:javascript
复制
#include <bits/stdc++.h>
using namespace std;
const int maxn = 2e5+7;
typedef pair<int,int> P;
struct N{
	int l,r,u,v;
}a[maxn];
int n,m;
int dep[maxn],pre[maxn],ans,tot;
int b[maxn];
vector<int> tr[maxn<<2];
int getf(int t){
	while(t!=pre[t]){
		t = pre[t];
	}
	return pre[t];
}
void update(int rt,int l,int r,int L,int R,int k){
	if(L<=l&&R>=r){
		tr[rt].push_back(k); 
		return ;
	}
	int mid = (l+r)>>1;
	if(L<=mid)update(rt<<1,l,mid,L,R,k);
	if(R>mid)update(rt<<1|1,mid+1,r,L,R,k);
}
void dfs(int rt,int l,int r){
	int sz = tr[rt].size();
	vector<P> tmp;
	for(int i=0;i<sz;i++){
		int t = tr[rt][i];
		int u = a[t].u, v = a[t].v;
		u = getf(u);	v = getf(v);
		if(u==v)continue;
		if(dep[u]<dep[v])
			pre[u] =  v, tmp.push_back(P{u,0});
		else if(dep[v]<dep[u])
			pre[v] = u, tmp.push_back(P{v,0});
		else 
			pre[u] = v,dep[v]++,tmp.push_back(P{u,1}); 
	}
	if(getf(1)==getf(n)){
		ans+=b[r+1] - b[l];
	}else if(l<r){
		int mid = (l+r)>>1;
		dfs(rt<<1,l,mid);
		dfs(rt<<1|1,mid+1,r);
	} 
	sz = tmp.size();
	for(int i = sz-1;i>=0;i--){
		P o = tmp[i];
		dep[ pre[o.first] ]-=o.second;
		pre[ o.first ] = o.first;
	}
}
int main()
{
	scanf("%d %d",&n,&m);
	for(int i=1;i<=n;i++){
		pre[i] = i;
		dep[i] = 0;
	}
	for(int i=1;i<=m;i++){
		scanf("%d %d %d %d",&a[i].u,&a[i].v,&a[i].l,&a[i].r);
		b[2*i-1] = a[i].l;
		b[2*i] = a[i].r + 1;
	} 
	sort(b+1,b+1+2*m);
	tot = unique(b+1,b+1+2*m) - b - 1;
	for(int i=1;i<=m;i++){
		a[i].l = lower_bound(b+1,b+1+tot,a[i].l) - b;
		a[i].r = lower_bound(b+1,b+1+tot,a[i].r+1) - b - 1;
		update(1,1,tot,a[i].l,a[i].r,i);	
	}
	dfs(1,1,tot);
	printf("%d\n",ans);
	return 0;
} 
本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2019年08月22日,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档