[CF786B] Legacy

Description

有 n 个点 ((nleq 10^5)),三种操作:

1 u v w 从u向v连一条权值为w的有向边

2 u L R w 从u向[L,R]的所有结点连一条权值为w的有向边

3 u L R w 从[L,R]的所有结点向u连一条权值为w的有向边

Solution

解锁了线段树优化建图的姿势。

感觉有点玄乎啊,优化建图实际上就是让线段树上的节点做一个中转,中转叶子节点到叶子节点的道路。

这老哥写的不错 戳我

注意边的空间要开大点!

Code

#include<queue>
#include<cstdio>
#include<cctype>
#include<cstring>
#define N 100005
#define int long long
#define min(A,B) ((A)<(B)?(A):(B))
#define max(A,B) ((A)>(B)?(A):(B))
#define swap(A,B) ((A)^=(B)^=(A)^=(B))

int vis[N<<2];
int root1,root2;
int n,m,s,cnt,tot;
int lch[N<<2],rch[N<<2];
int dis[N<<2],head[N<<2];

struct Edge{
	int to,nxt,dis;
}edge[N*20];

struct Node{
	int now,dis;
	friend bool operator<(Node a,Node b){
		return a.dis>b.dis;
	}
};

void add(int x,int y,int z){
	edge[++cnt].to=y;
	edge[cnt].nxt=head[x];
	edge[cnt].dis=z;
	head[x]=cnt;
}

void build1(int &cur,int l,int r){
	if(l==r){
		cur=l;
		return;
	}
	cur=++tot;
	int mid=l+r>>1;
	build1(lch[cur],l,mid);
	build1(rch[cur],mid+1,r);
	add(cur,lch[cur],0);add(cur,rch[cur],0);
}

void build2(int &cur,int l,int r){
	if(l==r){
		cur=l;
		return;
	}
	cur=++tot;
	int mid=l+r>>1;
	build2(lch[cur],l,mid);
	build2(rch[cur],mid+1,r);
	add(lch[cur],cur,0);add(rch[cur],cur,0);
}

int getint(){
	int x=0,f=0;char ch=getchar();
	while(!isdigit(ch)) f|=ch=='-',ch=getchar();
	while(isdigit(ch)) x=(x<<1)+(x<<3)+(ch^48),ch=getchar();
	return f?-x:x;
}

void modify1(int cur,int l,int r,int ql,int qr,int x,int y){
	if(ql<=l and r<=qr){
		add(x,cur,y);
		return;
	}
	int mid=l+r>>1;
	if(ql<=mid)
		modify1(lch[cur],l,mid,ql,qr,x,y);
	if(mid<qr)
		modify1(rch[cur],mid+1,r,ql,qr,x,y);
}

void modify2(int cur,int l,int r,int ql,int qr,int x,int y){
	if(ql<=l and r<=qr){
		add(cur,x,y);
		return;
	}
	int mid=l+r>>1;
	if(ql<=mid)
		modify2(lch[cur],l,mid,ql,qr,x,y);
	if(mid<qr)
		modify2(rch[cur],mid+1,r,ql,qr,x,y);
}

void dijkstra(){
	std::priority_queue<Node> pq;
	pq.push((Node){s,0});
	while(pq.size()){
		Node u=pq.top();pq.pop();
		if(vis[u.now]) continue;
		vis[u.now]=1;
		for(int i=head[u.now];i;i=edge[i].nxt){
			int to=edge[i].to;
			if(dis[to]>u.dis+edge[i].dis){
				dis[to]=u.dis+edge[i].dis;
				pq.push((Node){to,dis[to]});
			}
		}
	}
}

signed main(){
	n=getint(),m=getint(),s=getint();tot=n;
	build1(root1,1,n);build2(root2,1,n);
	while(m--){
		int opt=getint();
		if(opt==1){
			int a=getint(),b=getint(),c=getint();
			add(a,b,c);
		} else if(opt==2){
			int a=getint(),b=getint(),c=getint(),d=getint();
			modify1(root1,1,n,b,c,a,d);
		} else{
			int a=getint(),b=getint(),c=getint(),d=getint();
			modify2(root2,1,n,b,c,a,d);
		}
	}
	for(int i=1;i<=(n<<2);i++)
		dis[i]=2e18;
	dis[s]=0;
	dijkstra();
	for(int i=1;i<=n;i++){
		if(dis[i]>=2e18)
			printf("-1 ");
		else
			printf("%I64d ",dis[i]);
	}
	return 0;
}
原文地址:https://www.cnblogs.com/YoungNeal/p/9297023.html