线段树优化建图求问
  • 板块学术版
  • 楼主ShanQing
  • 当前回复9
  • 已保存回复9
  • 发布时间2023/7/24 15:28
  • 上次更新2023/11/3 07:54:50
查看原帖
线段树优化建图求问
368204
ShanQing楼主2023/7/24 15:28

这是P6348的AC代码。

//writer:Oier_szc

#include <bits/stdc++.h>
using namespace std;
const int N=6e5+5;
int n,m,p;
int head[N<<3],ne[N<<4],to[N<<4],w[N<<4],tot=0;
int now;
int leaf[N];
void add(int u,int v,int W)
{
	to[++tot]=v;
	w[tot]=W;
	ne[tot]=head[u];
	head[u]=tot;
}
void build(int u,int l,int r)
{
	if(l==r)
	{
		leaf[l]=u;
		return;
	}
	int mid=l+r>>1;
	add(u,u<<1,0);
	add(u,u<<1|1,0);
	build(u<<1,l,mid);
	build(u<<1|1,mid+1,r);
}
void build2(int u,int l,int r)
{
	add(u,u+4*n,0);
	//add(u+4*n,u,0);
	if(l==r)
	{
		return;
	}
	int mid=l+r>>1;
	add((u<<1)+4*n,u+4*n,0);
	add((u<<1|1)+4*n,u+4*n,0);
	build2(u<<1,l,mid);
	build2(u<<1|1,mid+1,r);
}
void update1(int u,int l,int r,int L,int R)
{
	if(L<=l&&r<=R)
	{
		add(now,u,1);
		return;
	}
	int mid=l+r>>1;
	if(L<=mid) update1(u<<1,l,mid,L,R);
	if(R>mid) update1(u<<1|1,mid+1,r,L,R);
}
void update2(int u,int l,int r,int L,int R)
{
	if(L<=l&&r<=R)
	{
		add(u+4*n,now,0);
		return;
	}
	int mid=l+r>>1;
	if(L<=mid) update2(u<<1,l,mid,L,R);
	if(R>mid) update2(u<<1|1,mid+1,r,L,R);
}
int dis[N<<3];
void bfs()
{
	memset(dis,0x3f,sizeof(dis));
	deque<int> q;
	q.push_front(leaf[p]);
	dis[leaf[p]]=0;
	while(!q.empty())
	{
		int now=q.front();
		q.pop_front();
		for(int i=head[now];i;i=ne[i])
		{
			if(dis[now]+w[i]<dis[to[i]])
			{
				dis[to[i]]=dis[now]+w[i];
				if(!w[i]) q.push_front(to[i]);
				else q.push_back(to[i]);
			}
		}
	}
}
int main()
{
	scanf("%d%d%d",&n,&m,&p);
	int a,b,c,d;
	build(1,1,n);
	build2(1,1,n);
	now=8*n+5;
	for(int i=1;i<=m;++i)
	{
		scanf("%d%d%d%d",&a,&b,&c,&d);
		++now;
		update1(1,1,n,a,b);
		update2(1,1,n,c,d);
		++now;
		update2(1,1,n,a,b);
		update1(1,1,n,c,d);
	}
	bfs();
	for(int i=1;i<=n;++i)
	{
		printf("%d\n",dis[leaf[i]]);
	}
	return 0;
}

但是szc对建图部分的add(u,u+4*n,0);有疑问。按道理入树和出树要建双向边,但是这里只能单向,双向会全WA,求原因。

2023/7/24 15:28
加载中...