CF786B Legacy

线段树优化建边的板子题

注意点到区间的连边和区间到点的连边需要两颗线段树。

点到区间连边时,由点指向区间,区间内部要从当前层向下连边,以保证点能到达区间内的每个点。

区间到点连边时,有区间指向点,区间内部要从当前层向上两边,以保证点能通过覆盖它的区间到达它能到达的点。

代码如下。

#include<iostream>
#include<cstdio>
#include<algorithm>
#include<string>
#include<cstring>
#include<cmath>
#include<queue>
#include<vector>
using namespace std;
typedef long long ll;
const ll N=4e5+10,inf=1e18;
struct node{
	ll l,r,in,out;
	#define l(x) tree[x].l
	#define r(x) tree[x].r
	#define in(x) tree[x].in
	#define out(x) tree[x].out
}tree[N*2];
ll n,m,s,cnt,vis[N],dis[N];priority_queue<pair<ll,ll> > q;vector<pair<ll,ll> > g[N];
inline ll read(){
	ll x=0,f=1;char ch=getchar();
	while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
	while(ch>='0'&&ch<='9'){x=(x<<1)+(x<<3)+ch-'0';ch=getchar();}
	return x*f;
}
inline void build(ll p,ll l,ll r){
	l(p)=l;r(p)=r;
	if(l==r){in(p)=out(p)=l;return;}
	in(p)=++cnt;out(p)=++cnt;
	ll mid=(l+r)>>1;
	build(p<<1,l,mid);build(p<<1|1,mid+1,r);
	g[in(p)].push_back(make_pair(in(p<<1),0ll));
	g[in(p)].push_back(make_pair(in(p<<1|1),0ll));
	g[out(p<<1)].push_back(make_pair(out(p),0ll));
	g[out(p<<1|1)].push_back(make_pair(out(p),0ll));
}
inline void in_change(ll p,ll l,ll r,ll w,ll s){
	if(l<=l(p)&&r(p)<=r){g[s].push_back(make_pair(in(p),w));return;}
	ll mid=(l(p)+r(p))>>1;
	if(l<=mid) in_change(p<<1,l,r,w,s);
	if(r>mid) in_change(p<<1|1,l,r,w,s);
}
inline void out_change(ll p,ll l,ll r,ll w,ll t){
	if(l<=l(p)&&r(p)<=r){g[out(p)].push_back(make_pair(t,w));return;}
	ll mid=(l(p)+r(p))>>1;
	if(l<=mid) out_change(p<<1,l,r,w,t);
	if(r>mid) out_change(p<<1|1,l,r,w,t);
}
inline void dijkstra(){
	for(ll i=1;i<=cnt;i++) dis[i]=inf;
	dis[s]=0;q.push(make_pair(0,s));
	while(q.size()){
		ll x=q.top().second;q.pop();
		if(vis[x]) continue;vis[x]=1;
		for(ll i=0;i<g[x].size();i++){
			ll y=g[x][i].first,z=g[x][i].second;
			if(dis[y]>dis[x]+z){
				dis[y]=dis[x]+z;q.push(make_pair(-dis[y],y));
			}
		}
	}
}
int main(){
	n=read();m=read();s=read();cnt=n;
	build(1ll,1ll,n);
	for(ll i=1;i<=m;i++){
		ll k=read(),s,t,l,r,w;
		if(k==1) s=read(),t=read(),w=read(),g[s].push_back(make_pair(t,w));
		else if(k==2) s=read(),l=read(),r=read(),w=read(),in_change(1ll,l,r,w,s);
		else if(k==3) t=read(),l=read(),r=read(),w=read(),out_change(1ll,l,r,w,t);
	}
	dijkstra();
	for(int i=1;i<=n;i++) printf("%lld ",(dis[i]==inf)?-1:dis[i]);
	return 0;
}

  

 

posted @ 2019-05-07 16:08  小塘一点空明  阅读(408)  评论(0编辑  收藏  举报