列表

详情


NC226052. 智乃酱的双塔问题·极(带修改的DP,DDP)

描述

如图所示,在某个地方有两座层数为的高塔,两座高塔的内部各自都有连接到上一层的楼梯,即每座塔的第层可以直接上楼梯到第层。
同时,在两座高塔之间还会存在一些连接两座高塔的楼梯,具体来说,除了顶层以外,每一层都是以下这两种情况之一。
  1. 左侧高塔的第层有楼梯连接右侧高塔的第层。
  2. 右侧高塔的第层有楼梯连接左侧高塔的第层。
假设层塔左侧楼梯、第层塔右侧楼梯、两座塔之间的楼梯,其高度分别为
楼梯的高度在这个问题中可能会随时被修改,同时,塔的结构也有可能改变,也就是说除了顶层以外,每一层都有可能从第1种情况改变成第2种情况,我们用字符'/'表示第1种情况,用字符'\'表示第2种情况。
现在智乃想知道,她从某座高塔的第层移动到层(),在只能走楼梯上楼的情况下,移动的最短路是多少?
当然,并不总是都可以到达目标地点,当不存在任何一条合法道路的时候,要求你输出表示无解。

输入描述

第一行输入两个正整数表示高塔的层数,以及询问的次数。
第二行输出一个长度大小为的字符串,字符串仅包括
接下来输入行,每行三个正整数,第层左侧塔上楼楼梯的长度,第层右侧塔上楼楼梯的长度,第层两座塔之间楼梯上楼的长度。
接下来行,每行首先输入一个非负整数表示操作的类型。

时,表示这是一个修改塔楼梯结构的操作。
接下来还会继续输入一个正整数和一个字符,表示第层的塔结构变为

时,表示这是一个修改塔楼梯长度的操作。
接下来还会继续输入四个正整数,表示修改后第层左侧塔上楼楼梯的长度,第层右侧塔上楼楼梯的长度,第层两座塔之间楼梯上楼的长度。

时,表示这是一个查询操作。
接下来还会继续输入四个整数,分别表示智乃酱一开始的层数,她想去的层数
为0时,表示一开始在左边的塔,否则表示一开始在右边的塔。
为0时,表示她的终点为左边的塔,否则表示终点为右边的塔。

输出描述

对于每一个输出一行,输出移动的最短路,如果无法到达则输出

示例1

输入:

4 13
///
1 2 1
2 3 5
8 8 1
2 1 4 1 0
0 3 \
2 1 4 0 0
2 2 4 0 0
2 2 4 0 1
2 3 4 0 1
2 3 4 1 0
1 1 1 1 1
1 2 1 1 1
1 3 1 1 1
2 1 4 1 0
0 3 /
2 1 4 1 0

输出:

-1
5
6
13
-1
1
3
-1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++ 解法, 执行用时: 228ms, 内存消耗: 15220K, 提交时间: 2021-08-23 17:29:19

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;
const int N=1e5+10;
const ll INF=1ll<<61;
char s[N];
int pos[N];
struct node
{
	int l,r;
	ll m[2][2];
	
	node operator*(const node x)const
	{
		node ret;
		ret.l=l;
		ret.r=x.r;
		for(int i=0;i<2;i++)
		{
			for(int j=0;j<2;j++)
			{
				ret.m[i][j]=INF;
				for(int k=0;k<2;k++)
				{
					ret.m[i][j]=min(ret.m[i][j],m[i][k]+x.m[k][j]);
				}
			}
		}
		return ret;
	}
}t[N<<2];
void pushup(int k)
{
	t[k]=t[k<<1]*t[k<<1|1];
}
void f(int k,ll v0,ll v1,ll v2,ll v3)
{
	t[k].m[0][0]=v0;
	t[k].m[0][1]=v1;
	t[k].m[1][0]=v2;
	t[k].m[1][1]=v3;
}
ll v0[N],v1[N],v2[N];
void build(int k,int l,int r)
{
	t[k].l=l;t[k].r=r;
	if(l==r)
	{
		pos[l]=k;
		if(s[l]=='/')f(k,v0[l],v2[l],INF,v1[l]);
		else f(k,v0[l],INF,v2[l],v1[l]);
		return ;
	}
	int mid=(l+r)>>1;
	build(k<<1,l,mid);
	build(k<<1|1,mid+1,r);
	pushup(k);
}
void update(int k)
{
	int root=pos[k];
	if(s[k]=='/')f(root,v0[k],v2[k],INF,v1[k]);
	else f(root,v0[k],INF,v2[k],v1[k]);
	while(root>>=1)pushup(root);
}
node query(int k,int l,int r)
{
	if(l<=t[k].l&&t[k].r<=r)
	{
		return t[k];
	}
	int mid=(t[k].l+t[k].r)>>1;
	if(r<=mid)return query(k<<1,l,r);
	else if(l>mid)return query(k<<1|1,l,r);
	else return query(k<<1,l,r)*query(k<<1|1,l,r);
}
int main()
{
	int n,m;
	scanf("%d%d",&n,&m);
	scanf("%s",s+1);
	for(int i=1;i<n;i++)
	{
		scanf("%lld%lld%lld",&v0[i],&v1[i],&v2[i]);
	}
	build(1,1,n);
	int hs,ht,ps,pt,op,x;
	char c[5];
	while(m--)
	{
		scanf("%d",&op);
		if(op==2)
		{
			scanf("%d%d%d%d",&hs,&ht,&ps,&pt);
			ll ans=query(1,hs,ht-1).m[ps][pt];
			if(ans==INF)ans=-1;
			printf("%lld\n",ans);
		}
		else 
		{
			if(op==0)
			{
				scanf("%d",&x);
				scanf("%s",c);
				s[x]=c[0];
			}
			else 
			{
				scanf("%d",&x);
				scanf("%lld%lld%lld",&v0[x],&v1[x],&v2[x]);
			}
			update(x);
		}
	}
	return 0;
}

上一题