zoukankan      html  css  js  c++  java
  • [笔记]线段树优化建图

    Aha

    用途

    CodeForces一道有趣的模板题

    用于短时间内完成:

    • 点和区间
    • 区间和点
    • 区间和区间

    之间的连边

    方法

    初始

    整俩线段树

    我们维护两棵线段树(A,B),其中一棵每一个节点向父亲连代价为(0)的边,另一棵每一个节点向儿子连代价为(0)的边。再把对应的叶子节点之间相连(在建图的时候可以直接使叶子节点标号相同)

    然后你是不是已经会了

    放上丑丑的代码qwq

    	int BUILD(int l,int r,int pd){
    		if(l==r)return l;
    		int x=++tot;
    		int mid=(l+r)>>1;
    		son[x][0]=BUILD(l,mid,pd);
    		son[x][1]=BUILD(mid+1,r,pd);
    		if(pd==0)rep(i,0,1)ADD(son[x][i],x,0);
    		else rep(i,0,1)ADD(x,son[x][i],0);
    		return x;
    	}
    

    连边

    点——区间:点(u)([l,r])的每个点连代价为(w)的边

    蓝色的是目标区间,粉红色的是线段树区间查询时完全被覆盖的点

    那么点向区间连边,只需要把点和(A)树上对于的区间之间连一条代价为(w)的边,就可以通过线段树上的黑边不花费任何代价走到区间里的每一个点

    区间——点:区间([l,r])里的每一个点向点(u)连代价为(w)的边

    同样的道理,只需要从(B)树上对应的区间向(u)连代价为(w)的边,那么区间里的点就可以花费0的代价从黑边走到粉色节点,再花费(w)的代价走橙边到(u)

    区间——区间:区间([l_1,r_1])([l_2,r_2])连边

    发现区间和区间之间不太好搞哎

    我们可以建一个新的节点(u),B树上的对应区间向(u)连边,(u)向A树上的对应区间连边,就转化成了上面的两种情况啦

    具体实现的话可以一起写,找到对应节点再特判怎么连边就可以了

    void UPD(int x,int l,int r,int la,int ra,int pos,LL val,int pd){
    		if(l==la&&r==ra){
    			if(pd==2)ADD(pos,x,val);
    			else ADD(x,pos,val);//特判
    			return;
    		}
    		int mid=(l+r)>>1;
    		if(la>mid)UPD(son[x][1],mid+1,r,la,ra,pos,val,pd);
    		else if(ra<=mid)UPD(son[x][0],l,mid,la,ra,pos,val,pd);
    		else{
    			UPD(son[x][0],l,mid,la,mid,pos,val,pd);
    			UPD(son[x][1],mid+1,r,mid+1,ra,pos,val,pd);
    		}
    	}
    

    求值

    最后跑一遍Dijkstra就可以啦

    代码

    注意

    • 数组要开够
    • 最后跑最短路的时候是对所有线段树上的点跑,而不是只对(n)个点跑

    猴啦放上完整代码

    #include<bits/stdc++.h>
    #define rep(X,A,B) for(int X=A;X<=B;X++)
    #define tep(X,A,B) for(int X=A;X>=B;X--)
    #define LL long long
    const int N=100010;
    const int NN=400010;
    const int M=6000010;
    using namespace std;
    
    int n,m,S;
    int vis[NN];
    LL dis[NN],wei[M];
    int son[NN][2],tot=0;
    int edge[M],lst[NN],nxt[M],t=0;
    
    struct nn{
    	int id;
    	LL dis;
    	
    	bool operator < (const nn &A) const {
    		return dis > A.dis;
    	}
    };
    
    priority_queue<nn>Q;
    
    void ADD(int x,int y,LL z){
    	edge[++t]=y;nxt[t]=lst[x];lst[x]=t;wei[t]=z;
    }
    
    struct SegmentTree{
    	int RT;
    	
    	int BUILD(int l,int r,int pd){
    		if(l==r)return l;
    		int x=++tot;
    		int mid=(l+r)>>1;
    		son[x][0]=BUILD(l,mid,pd);
    		son[x][1]=BUILD(mid+1,r,pd);
    		if(pd==0)rep(i,0,1)ADD(son[x][i],x,0);
    		else rep(i,0,1)ADD(x,son[x][i],0);
    		return x;
    	}
    
    	void UPD(int x,int l,int r,int la,int ra,int pos,LL val,int pd){
    		if(l==la&&r==ra){
    			if(pd==2)ADD(pos,x,val);
    			else ADD(x,pos,val);
    			return;
    		}
    		int mid=(l+r)>>1;
    		if(la>mid)UPD(son[x][1],mid+1,r,la,ra,pos,val,pd);
    		else if(ra<=mid)UPD(son[x][0],l,mid,la,ra,pos,val,pd);
    		else{
    			UPD(son[x][0],l,mid,la,mid,pos,val,pd);
    			UPD(son[x][1],mid+1,r,mid+1,ra,pos,val,pd);
    		}
    	}
    }ta,tb;
    
    void INIT(){
    	scanf("%d%d%d",&n,&m,&S);
    	tot=n;
    	ta.RT=ta.BUILD(1,n,0);
    	tb.RT=tb.BUILD(1,n,1);
    }
    
    void SOLVE(){
    	int pd,u,v,l,r;
    	LL w;
    	scanf("%d",&pd);
    	if(pd==1){
    		scanf("%d%d%lld",&u,&v,&w);
    		ADD(u,v,w);
    	}
    	else{
    		scanf("%d%d%d%lld",&u,&l,&r,&w);
    		if(pd==2)tb.UPD(tb.RT,1,n,l,r,u,w,pd);
    		else ta.UPD(ta.RT,1,n,l,r,u,w,pd);
    	}
    }
    
    void DIJ(){
    	rep(i,1,tot)dis[i]=-1,vis[i]=0;
    	dis[S]=0;Q.push((nn){S,0});
    	while(!Q.empty()){
    		int x=Q.top().id;Q.pop();
    		if(vis[x])continue;
    		vis[x]=1;
    		for(int r=lst[x];r;r=nxt[r]){
    			if(dis[edge[r]]!=-1&&dis[edge[r]]<=dis[x]+wei[r])continue;
    			dis[edge[r]]=dis[x]+wei[r];
    			Q.push((nn){edge[r],dis[edge[r]]});
    		}
    	}
    	rep(i,1,n)printf("%lld ",dis[i]);
    }
    
    int main(){
    	INIT();
    	rep(i,1,m)SOLVE();
    	DIJ();
    	return 0;
    }
    
  • 相关阅读:
    友盟上报 IOS
    UTF8编码
    Hill加密算法
    Base64编码
    Logistic Regression 算法向量化实现及心得
    152. Maximum Product Subarray(中等, 神奇的 swap)
    216. Combination Sum III(medium, backtrack, 本类问题做的最快的一次)
    77. Combinations(medium, backtrack, 重要, 弄了1小时)
    47. Permutations II(medium, backtrack, 重要, 条件较难思考)
    3.5 find() 判断是否存在某元素
  • 原文地址:https://www.cnblogs.com/SCL123/p/11858154.html
Copyright © 2011-2022 走看看