Luogu CF786B Legacy

https://www.luogu.org/problemnew/show/CF786B

 CF786B Legacy

 提交  题解   

  • 提示:收藏到任务计划后,可在首页查看。

最新讨论显示

推荐的相关题目显示

题意翻译

Rick和他的同事们做出了一种新的带放射性的婴儿食品(???根据图片和原文的确如此...),与此同时很多坏人正追赶着他们。因此Rick想在坏人们捉到他之前把他的遗产留给Morty。

在宇宙中一共有n个星球标号为1到n。Rick现在身处于标号为s的星球(地球)但是他不知道Morty在哪里。众所周知,Rick有一个传送枪,他用这把枪可以制造出一个从他所在的星球通往其他星球(也包括自己所在的星球)的单行道路。但是由于他还在用免费版,因此这把枪的使用是有限制的。

默认情况下他不能用这把枪开启任何传送门。在网络上有q个售卖这些传送枪的使用方案。每一次你想要实施这个方案时你都可以购买它,但是每次购买后只能使用一次。每个方案的购买次数都是无限的。

网络上一共有三种方案可供购买: 1.开启一扇从星球v到星球u的传送门; 2.开启一扇从星球v到标号在[l,r]区间范围内任何一个星球的传送门。(即这扇传送门可以从一个星球出发通往多个星球) 3.开启一扇从标号在[l,r]区间范围内任何一个星球到星球v的传送门。(即这扇传送门可以从多个星球出发到达同一个星球)

Rick并不知道Morty在哪儿,但是Unity将要通知他Morty的具体位置,并且他想要赶快找到通往所有星球的道路各一条并立刻出发。因此对于每一个星球(包括地球本身)他想要知道从地球到那个星球所需的最小钱数。

输入数据: 输入数据的第一行包括3个整数n,q和s(1<=n,q<=10^5,1<=s<=n)分别表示星球的数目,可供购买的方案数目以及地球的标号。

接下来的q行表示q种方案。 1.输入1 v u w表示第一种方案,其中v,u意思同上,w表示此方案价格。 2.输入2 v l r w表示第二种方案,其中v,l,r意思同上,w表示此方案价格。 2.输入3 v l r w表示第三种方案,其中v,l,r意思同上,w表示此方案价格。 (1<=v,u,l,r<=n,1<=w<=10^9)

输出格式: 输出一行用空格隔开的n个整数分别表示从地球到第i个星球所需的最小钱数。

说明: 在第一组测试样例里,Rick可以先购买第4个方案再购买第2个方案从而到达标号为2的星球.

感谢@radish布団 提供的翻译

题目描述

Rick and his co-workers have made a new radioactive formula and a lot of bad guys are after them. So Rick wants to give his legacy to Morty before bad guys catch them.

There are nn planets in their universe numbered from 11 to nn . Rick is in planet number ss (the earth) and he doesn't know where Morty is. As we all know, Rick owns a portal gun. With this gun he can open one-way portal from a planet he is in to any other planet (including that planet). But there are limits on this gun because he's still using its free trial.

By default he can not open any portal by this gun. There are qq plans in the website that sells these guns. Every time you purchase a plan you can only use it once but you can purchase it again if you want to use it more.

Plans on the website have three types:

  1. With a plan of this type you can open a portal from planet vv to planet uu .
  2. With a plan of this type you can open a portal from planet vv to any planet with index in range [l,r][l,r] .
  3. With a plan of this type you can open a portal from any planet with index in range [l,r][l,r] to planet vv .

Rick doesn't known where Morty is, but Unity is going to inform him and he wants to be prepared for when he finds and start his journey immediately. So for each planet (including earth itself) he wants to know the minimum amount of money he needs to get from earth to that planet.

输入输出格式

输入格式:

 

The first line of input contains three integers nn , qq and ss ( 1<=n,q<=10^{5}1<=n,q<=105 , 1<=s<=n1<=s<=n ) — number of planets, number of plans and index of earth respectively.

The next qq lines contain the plans. Each line starts with a number tt , type of that plan ( 1<=t<=31<=t<=3 ). If t=1t=1 then it is followed by three integers vv , uu and ww where ww is the cost of that plan ( 1<=v,u<=n1<=v,u<=n , 1<=w<=10^{9}1<=w<=109 ). Otherwise it is followed by four integers vv , ll , rr and ww where ww is the cost of that plan ( 1<=v<=n1<=v<=n , 1<=l<=r<=n1<=l<=r<=n , 1<=w<=10^{9}1<=w<=109 ).

 

输出格式:

 

In the first and only line of output print nn integers separated by spaces. ii -th of them should be minimum money to get from earth to ii -th planet, or -1−1 if it's impossible to get to that planet.

 

输入输出样例

输入样例#1: 复制

3 5 1
2 3 2 3 17
2 3 2 2 16
2 2 2 3 3
3 3 1 1 12
1 3 3 17

输出样例#1: 复制

0 28 12 

输入样例#2: 复制

4 3 1
3 4 1 3 12
2 2 3 4 10
1 2 4 16

输出样例#2: 复制

0 -1 -1 12 

说明

In the first sample testcase, Rick can purchase 44 th plan once and then 22 nd plan in order to get to get to planet number 22 .

 

 

 

这是一道裸题,前提是你会线段树建边

有题目描述可以发现区间是连续的,什么东西是靠连续的区间维护吃饭的?

线段树,它是维护一个个区间的,并且任何一段连续的序列在线段树上分成的子序列不多,不会超过lg n个

自己想想如何维护吧

毕竟博主也是自己听到线段树后想通的,

————————————————————————————————罪恶的分割线

如果只有1,2操作,就只用构造一棵线段树,

但是多了3操作后就要两棵,

菜鸡组织不出语言如何写

#include<cstdio>
#include<queue>
#define ll long long
using namespace std;

int read()
{
	int ret=0; char ch=getchar();
	while(ch<'0'||ch>'9') ch=getchar();
	while(ch>='0'&&ch<='9')
		ret=(ret<<1)+(ret<<3)+ch-'0',ch=getchar();
	return ret;
}

const int N=3e6+5;
int n,T,tot,s;
ll d[N];
bool fl[N];
int cnt,to[N],nxt[N],he[N],w[N];

struct B{int id; ll x; };
bool operator> (B i,B j)
{
	return i.x>j.x;
}
priority_queue<B,vector<B>,greater<B> >q;

inline void add(int u,int v,int k)
{
	to[++cnt]=v,nxt[cnt]=he[u];
	he[u]=cnt,w[cnt]=k;
}

struct A
{
	int id1[N],id2[N];
	void build1(int p,int l,int r)
	{
		if(l==r) 
		{
			id1[p]=l;
			return;
		}
		id1[p]=++tot;
		int mid=l+r>>1;
		build1(p<<1,l,mid);
		build1(p<<1|1,mid+1,r);
		add(id1[p],id1[p<<1],0);
		add(id1[p],id1[p<<1|1],0);
	}
	
	void build2(int p,int l,int r)
	{
		if(l==r)
		{
			id2[p]=l;
			return;
		}
		id2[p]=++tot;
		int mid=l+r>>1;
		build2(p<<1,l,mid);
		build2(p<<1|1,mid+1,r);
		add(id2[p<<1],id2[p],0);
		add(id2[p<<1|1],id2[p],0);
	}
	
	void find1(int p,int l,int r,int u,int x,int y,int k)
	{
		if(l==x&&r==y) 
		{
			add(u,id1[p],k);
			return;
		}
		int mid=l+r>>1;
		if(mid>=y) find1(p<<1,l,mid,u,x,y,k);
			else if(mid<x) find1(p<<1|1,mid+1,r,u,x,y,k);
				else find1(p<<1,l,mid,u,x,mid,k),
					 find1(p<<1|1,mid+1,r,u,mid+1,y,k);
	}
	
	void find2(int p,int l,int r,int u,int x,int y,int k)
	{
		if(l==x&&r==y)
		{
			add(id2[p],u,k);
			return;
		}
		int mid=l+r>>1;
		if(mid>=y) find2(p<<1,l,mid,u,x,y,k);
			else if(mid<x) find2(p<<1|1,mid+1,r,u,x,y,k);
				else find2(p<<1,l,mid,u,x,mid,k),
					 find2(p<<1|1,mid+1,r,u,mid+1,y,k);
	}
}tree;

int main()
{
	n=read(),T=read(),s=read();
	tot=n;
	tree.build1(1,1,n);
	tree.build2(1,1,n);
	while(T--)
	{
		int t=read();
		if(t==1) 
		{
			int u=read(),v=read(),k=read();
			add(u,v,k);
		}else
		if(t==2)
		{
			int u=read(),l=read(),r=read(),k=read();
			tree.find1(1,1,n,u,l,r,k);
		}else
		{
			int u=read(),l=read(),r=read(),k=read();
			tree.find2(1,1,n,u,l,r,k);
		}
	}
	for(int i=1;i<=tot;i++) d[i]=1e18;
	q.push((B){s,d[s]=0});
	while(!q.empty())
	{
		while(!q.empty()&&fl[q.top().id]) q.pop();
		if(q.empty()) break;
		int u=q.top().id; q.pop(),fl[u]=1;
		for(int e=he[u];e;e=nxt[e])
		{
			int v=to[e];
			if(!fl[v]&&d[v]>d[u]+w[e]) 
				q.push((B){v,d[v]=d[u]+w[e]});
		}
	}
	for(int i=1;i<=n;i++)
		printf("%lld%c",d[i]==1e18?-1:d[i],i==n?'\n':' ');
	return 0;
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值