• CF786B Legacy


    线段树优化建图

    开一棵儿子向父亲连0边的线段树1

    另一棵父亲向儿子连0边的线段树0

    0向1的对应节点连0边

    对于点向区间加边,我们从1对应的节点向0对应的区间连边

    对于区间向点加边,我们从1对应的区间向0对应的节点连边

    然后跑手写堆优化Dijkstra即可

    时间复杂度(Theta ((n+mlog n)log n))

    #include"cstdio"
    #include"cstring"
    #include"iostream"
    #include"algorithm"
    using namespace std;
    
    const int MAXN=1<<17;
    
    int n,m,s,np,siz;
    int h[MAXN<<2],hp[MAXN<<2],id[MAXN<<2],rid[MAXN];
    long long ln[MAXN<<2];
    struct rpg{
    	int li,nx,ln;
    }a[MAXN<<4];
    
    void add(int ls,int nx,int ln){a[++np]=(rpg){h[ls],nx,ln};h[ls]=np;}
    
    void res(int k,int l,int r)
    {
    	siz=max(siz,k);
    	if(l==r) return;
    	int i=k<<1,mid=l+r>>1;
    	res(i,l,mid);res(i|1,mid+1,r);
    	return;
    }
    
    void build(int k,int l,int r)
    {
    	add(k,k+siz,0);
    	if(l==r){rid[l]=k;return;}
    	int i=k<<1,mid=l+r>>1;
    	build(i,l,mid);build(i|1,mid+1,r);
    	add(k,i,0);add(k,i|1,0);
    	add(i+siz,k+siz,0);add((i|1)+siz,k+siz,0);
    	return;
    }
    
    void slv1()
    {
    	int x,y,z;scanf("%d%d%d",&x,&y,&z);
    	add(rid[x]+siz,rid[y],z);
    	return;
    }
    
    void cadd(int k,int l,int r,int le,int ri,int ln,int x,bool kd)
    {
    	if(le<=l&&r<=ri){
    		if(!kd) add(x,k,ln);
    		else add(k+siz,x,ln);
    		return;
    	}int i=k<<1,mid=l+r>>1;
    	if(le<=mid) cadd(i,l,mid,le,ri,ln,x,kd);
    	if(mid<ri) cadd(i|1,mid+1,r,le,ri,ln,x,kd);
    	return;
    }
    
    void slv2()
    {
    	int x,y1,y2,z;scanf("%d%d%d%d",&x,&y1,&y2,&z);
    	cadd(1,1,n,y1,y2,z,rid[x]+siz,0);
    	return;
    }
    
    void slv3()
    {
    	int x1,x2,y,z;scanf("%d%d%d%d",&y,&x1,&x2,&z);
    	cadd(1,1,n,x1,x2,z,rid[y],1);
    	return;
    }
    
    void up(int x)
    {
    	for(int i=x,j=i>>1;j;i=j,j>>=1){
    		if(ln[hp[i]]<ln[hp[j]]) swap(hp[i],hp[j]),swap(id[hp[i]],id[hp[j]]);
    		else break;
    	}return;
    }
    
    void ins(int x)
    {
    	hp[++hp[0]]=x;
    	id[x]=hp[0];
    	up(hp[0]);
    	return;
    }
    
    void pop()
    {
    	id[hp[1]]=0;
    	hp[1]=hp[hp[0]--];
    	id[hp[1]]=1;
    	for(int i=1,j=2;j<=hp[0];i=j,j<<=1){
    		if(j<hp[0]&&ln[hp[j+1]]<ln[hp[j]]) ++j;
    		if(ln[hp[i]]>ln[hp[j]]) swap(hp[i],hp[j]),swap(id[hp[i]],id[hp[j]]);
    		else break;
    	}return;
    }
    
    void Dijkstra(int s)
    {
    	memset(ln,0x7f,sizeof(ln));
    	ln[s]=0;ins(s);
    	while(hp[0]){
    		int nw=hp[1];pop();
    		for(int i=h[nw];i;i=a[i].li){
    			if(ln[a[i].nx]>ln[nw]+a[i].ln){
    				ln[a[i].nx]=ln[nw]+a[i].ln;
    				if(id[a[i].nx]) up(id[a[i].nx]);
    				else ins(a[i].nx);
    			}
    		}
    	}return;
    }
    
    int main()
    {
    	scanf("%d%d%d",&n,&m,&s);
    	res(1,1,n);
    	build(1,1,n);
    	while(m--){
    		int c;scanf("%d",&c);
    		if(c==1) slv1();
    		else if(c==2) slv2();
    		else slv3();
    	}Dijkstra(rid[s]);
    	for(int i=1;i<=n;++i) printf("%lld ",ln[rid[i]]<1e15?ln[rid[i]]:-1ll);
    	return 0;
    }
    
  • 相关阅读:
    SQLServer 事物与索引
    SQLServer 常见SQL笔试题之语句操作题详解
    测试思想-测试设计 测试用例设计之边界值分析方法
    测试思想-测试设计 测试用例设计之等价类划分方法
    测试思想-测试设计 测试用例设计之因果图方法
    测试思想-测试设计 测试用例设计之判定表驱动分析方法
    MySql 缓存查询原理与缓存监控 和 索引监控
    测试思想-测试设计 授客细说场景测试用例设计与实践
    产品相关 细说软件产品和业务 & 业务过程(流程) & 业务逻辑
    Postman Postman接口测试工具使用简介
  • 原文地址:https://www.cnblogs.com/AH2002/p/10097787.html
Copyright © 2020-2023  润新知