• [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;
    }
    
  • 相关阅读:
    74.Android之四种启动模式
    Android面试总结 (转)
    1.Android常见异常:android.view.WindowLeaked 分析以及解决办法
    73.Android之SparseArray替代HashMap
    C#(类)
    C#(一维数组)
    C#(二维数组/集合)
    c#(特殊集合)
    C#字符串去除html格式
    获取文件的后缀名 和 Process进程
  • 原文地址:https://www.cnblogs.com/YoungNeal/p/9297023.html
Copyright © 2020-2023  润新知