CF786B Legacy

CF786B Legacy

线段树优化建图板子题。

首先对于题目的三种连边方式,我们可以通过三种办法来分别维护。

点点连边直接 Addedge 即可。

点->区间 连边可以建立一棵线段树,这个线段树代表区间和普通的一样,只不过在建树的时候连接两条边权为 0 的边到左右区间即可。

区间->点 连边可以再建立一个线段树,然后这个线段树就是拿来反向连边的。

最后就是直接最短路即可。

具体实现看代码:

#include<bits/stdc++.h>
using namespace std;
template <typename T>
inline void read(T &x){
	x=0;char ch=getchar();bool f=false;
	while(!isdigit(ch)){if(ch=='-'){f=true;}ch=getchar();}
	while(isdigit(ch)){x=(x<<1)+(x<<3)+(ch^48);ch=getchar();}
	x=f?-x:x;
	return ;
}
template <typename T>
inline void write(T x){
	if(x<0) putchar('-'),x=-x;
	if(x>9) write(x/10);
	putchar(x%10^48);
	return ;
}
const int N=3e5+5,M=2e6+5;
#define ll long long
int n,q,s,cur,root[3];
int ls[M],rs[M];
int head[M],nex[M],to[M],idx;
ll val[M];
inline void add(int u,int v,ll w){
	nex[++idx]=head[u];
	to[idx]=v;
	val[idx]=w;
	head[u]=idx;
	return ;
}
void Build(int &x,int l,int r,int type){
	if(l==r) return x=l,void();
	int mid=l+r>>1;x=++cur;
	Build(ls[x],l,mid,type),Build(rs[x],mid+1,r,type);
	if(type==2) add(x,ls[x],0),add(x,rs[x],0);
	else add(ls[x],x,0),add(rs[x],x,0);
	return ;
}
void Modify(int x,int l,int r,int ql,int qr,int u,ll w,int type){
	if(ql<=l&&r<=qr) return type==2?add(u,x,w):add(x,u,w),void();
	int mid=l+r>>1;
	if(ql<=mid) Modify(ls[x],l,mid,ql,qr,u,w,type);
	if(qr>mid) Modify(rs[x],mid+1,r,ql,qr,u,w,type);
	return ;
}
ll dis[M];
bool vis[M];
typedef pair<ll,int> PII;
priority_queue<PII,vector<PII>,greater<PII> >que;
void Dijkstra(){
	memset(dis,0x3f,sizeof(dis));
	dis[s]=0;
	que.push({0,s});
	while(!que.empty()){
		PII t=que.top();que.pop();
		int x=t.second;ll dist=t.first;
		if(vis[x]) continue;
		vis[x]=true;
		for(int i=head[x];i;i=nex[i]){
			int y=to[i];
			if(dis[y]>dist+val[i]){
				dis[y]=dist+val[i];
				que.push({dis[y],y});
			}
		}
	}
	return ;
}
signed main(){
	read(n),read(q),read(s);cur=n;
	Build(root[1],1,n,2);Build(root[2],1,n,3);
	for(int i=1;i<=q;i++){
		int op,l,r,u,v;ll w;
		read(op);
		if(op==1) read(u),read(v),read(w),add(u,v,w);
		else read(u),read(l),read(r),read(w),Modify(root[op-1],1,n,l,r,u,w,op);
	}
	Dijkstra();
	for(int i=1;i<=n;i++) write(dis[i]==dis[(M)-100]?-1:dis[i]),putchar(' ');
	return 0;
}
原文地址:https://www.cnblogs.com/Akmaey/p/14676998.html