• 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;
    }
    
  • 相关阅读:
    Oracle使用笔记
    跳转至锚点
    项目中使用到的AOP
    短信验证码接口使用
    阿里人脸识别接口
    java实现网页截图
    java后台接收微信服务号/订阅号消息
    java 实现redis缓存
    redis 常用命令
    被骗了,自己还不知道
  • 原文地址:https://www.cnblogs.com/Akmaey/p/14676998.html
Copyright © 2020-2023  润新知