CF786B Legacy

线段树优化建图

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

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

0向1的对应节点连0边

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

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

然后跑手写堆优化Dijkstra即可

时间复杂度\(\Theta ((n+m\log 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;
}
posted @ 2018-12-10 17:38  A·H  阅读(133)  评论(0编辑  收藏  举报