Codeforces 1279C Stack of Presents

文章讨论了圣诞老人在给定堆中按特定顺序发送礼物的问题,考虑了礼物重新排序以最小化总时间。通过记录礼物堆的深度,计算取每个礼物所需的时间,得出在每次返回堆时进行最佳排序的最短时间。
摘要由CSDN通过智能技术生成

圣诞老人必须送礼物给孩子们。他有一堆 n 个礼物,编号从1到 n;最上面的礼物编号为 a1,接下来的礼物为 a2,依此类推;最底部的礼物编号为 an。所有编号都是不同的。

圣诞老人有一个要送出的礼物清单,包含 m 个不同的礼物:b1,b2,...,bm。他将按照清单中的顺序发送这些礼物。

为了发送一个礼物,圣诞老人必须从堆中找到它,移除所有在它上面的礼物,拿走这个礼物,然后将所有被移除的礼物放回堆中。所以,如果在圣诞老人想要发送的礼物上方有 k 个礼物,那么他需要花费 2k+1 秒来完成这个过程。幸运的是,圣诞老人可以加快整个过程 — 当他将礼物放回堆中时,他可以根据需要重新排列它们(只能重新排列那些在他想要拿走的礼物上方的礼物;下面的礼物不能受到任何影响)。

在已知要送出的礼物清单并且每次将礼物返回堆时都进行最佳重新排序的情况下,发送所有礼物所需的最短时间是多少?圣诞老人不能改变礼物的顺序或以其他方式干预礼物堆。

你的程序必须回答 t 个不同的测试用例。

输入
第一行包含一个整数 t(1≤t≤100)— 测试用例的数量。

然后是测试用例,每个用三行表示。

第一行包含两个整数 n 和 m(1≤m≤n≤105)— 堆中礼物的数量和圣诞老人想要发送的礼物数量。

第二行包含 n 个整数 a1,a2,...,an(1≤ai≤n,所有 ai 都是唯一的)— 堆中礼物的顺序。

第三行包含 m 个整数 b1,b2,...,bm(1≤bi≤n,所有 bi 都是唯一的)— 圣诞老人要发送的礼物的顺序。

所有测试用例中 n 的总和不超过 105。

输出
对于每个测试用例,输出一个整数 — 圣诞老人发送礼物所需的最短时间,如果他每次将礼物返回堆时都进行最佳重新排序。

解析:排序不消耗时间,每次取完后都是最佳排序(即在排序内只要2*0+1秒)

            只需记录最深点,如果小于最深点便是排好序的+1,如果不是便更新最深点同时需要把上方全部拿起2*k+1;

                为了体现从上到下将a[i]存进数组st[a[i]]=i;这样对b[i]遍历时st[b[i]]的值既是对应元素的深度。

代码:

#include<bits/stdc++.h>
using namespace std;
const int N=2e5+10;
int a[N],b[N],st[N];
int n,m;

void slove(){
	cin>>n>>m;
	memset(a,0,sizeof a);
	memset(b,0,sizeof b);
	for(int i=1;i<=n;i++){
		cin>>a[i];
		st[a[i]]=i;
	}
	int mx=0;
	long long ans=0;
	for(int i=1;i<=m;i++){
	    cin>>b[i];
		if(st[b[i]]>mx)ans+=2*(st[b[i]]-i)+1;
		else ans++;
		mx=max(mx,st[b[i]]);
	}
	cout<<ans<<"\n";
}
int main(){
	cin.tie(0);
	cout.tie(0);
	ios::sync_with_stdio(0);
	int t;
	cin>>t;
	while(t--){
		slove();
	}
	return 0;
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值