打卡信奥刷题(1706)用C++实现信奥 P8345 「Wdoi-6」华胥之梦

P8345 「Wdoi-6」华胥之梦

题目背景

题目描述

简要题意

给定长度为 n n n 的序列 a a a 和常数 c c c。构造点数为 n n n 的有向完全图 G G G 使得边 i → j i\to j ij i ≠ j i\neq j i=j)的长度为 a i − 2 a j + c a_i-2a_j+c ai2aj+c,保证所有边权非负

接下来给出 q q q 次询问,每次给出一个点集,试找出图 G G G 的一条最短的简单路径,满足其经过点集中所有点,并输出它的长度。


原始题意

梅莉做了一个梦,梦到自己穿越到了幻想乡的迷途竹林之中。醒来之后,她希望能够和莲子一起再次穿越境界,进入幻想乡。

但是,这一次,她看到了 n n n 个世界,其中,第 i i i 个世界的结界强度为 a i a_i ai。而世界之间两两都有通道相连,莲子和梅莉便是通过这些通道来进行世界之间的穿梭的。

为了避免错过幻想乡所在的世界,因此她们每到达一个世界,都会穿越结界。莲子和梅莉从第 i i i 个世界中,通过一条通道,再穿越结界进入第 j j j 个世界,需要使用的灵能为 a i − 2 a j + c a_i-2a_j+c ai2aj+c(保证所需消耗的灵能非负),其中 c c c 是一个常数,是梅莉每次穿越结界需要的额外灵能消耗。注意,这也意味着,从第 i i i 个世界到第 j j j 个世界,与第 j j j 个世界穿越到第 i i i 个世界所消耗的灵能,可能是不同的

为了能够高效地找到幻想乡,她们会对你进行 q q q 次询问,每次询问的时候会给出一个集合,表示她们想要进入的世界。由于世界众多,她们希望能够节省灵能,因此她希望你能求出所有包含这些世界的简单路径(即:同一条世界间的通道不会被走多次)中,消耗灵能值之和最少的路径。你只需告诉她们消耗灵能值之和最少为多少。

输入格式

  • 第一行三个整数 n , c , q n,c,q n,c,q
  • 第二行 n n n 个整数表示数列 a a a
  • 接下来 q q q 行。每行第一个整数 ∣ S ∣ |S| S,即集合 S S S 的大小。后面 ∣ S ∣ |S| S 个互不相同的整数表示集合 S S S

输出格式

  • 输出共 q q q 行,每行一个整数,表示询问的答案。

输入输出样例 #1

输入 #1

5 20 3
7 4 2 5 9
2 1 4
3 1 2 3
4 1 4 2 5

输出 #1

11
24
34

输入输出样例 #2

输入 #2

10 928698067 3
331485039 15480787 61584781 252174726 472089427 95998831 252561792 118119945 315548522 24453837
4 9 1 10 2
5 10 6 1 5 8
1 5

输出 #2

1798602551
2249463436
0

说明/提示

样例解释

样例 #1

每两个点之间的边权如图所示。为了便于选手观察,边权的颜色与它所对应的边的颜色相同。

对于第一个询问,可以找到路径 4 → 1 4\to 1 41
;对于第二个询问,可以找到路径 3 → 2 → 1 3\to 2\to 1 321;对于第三个询问,可以找到路径 2 → 4 → 1 → 5 2\to 4 \to 1\to 5 2415。可以证明,这三个方案分别是对应询问的最优方案。

样例 #2

该样例符合 Subtask   1 \textbf{Subtask 1} Subtask 1 的限制。

数据范围

本题采用捆绑测试。

Subtask 分值 n ≤ q ≤ ∑ ∣ S ∣ ≤ 特殊性质 Subtask   依赖 1 30 10 10 10 − − 2 20 1 0 5 1 0 5 1 0 5 A − 3 20 1 0 5 1 0 5 1 0 5 B − 4 30 1 0 6 1 0 6 1 0 6 − 1 , 2 , 3 \def\arraystretch{1.5} \begin{array}{|c|c|c|c|c|c|c|}\hline \textbf{Subtask} & \textbf{\textsf{分值}} & \bm{n\le } & \bm{q\le} & \bm{\sum |S|\le} & \textbf{\textsf{特殊性质}}&\textbf{Subtask \textsf{依赖}}\cr\hline 1 & 30 & 10 & 10 & 10 & - &-\cr\hline 2 & 20 & 10^5 & 10^5 & 10^5 & \mathbf{A}&- \cr\hline 3 & 20 & 10^5 & 10^5 & 10^5 & \mathbf{B}&- \cr\hline 4 & 30 & 10^6 & 10^6 & 10^6& -&1,2,3 \cr\hline \end{array} Subtask1234分值30202030n10105105106q10105105106S10105105106特殊性质ABSubtask 依赖1,2,3

  • 特殊性质 A \bf A A a i a_i ai 单调递增。
  • 特殊性质 B \bf B B a i a_i ai 全部相等。

对于 100 % 100\% 100% 的数据,保证 1 ≤ S i ≤ n ≤ 1 0 6 , 1 ≤ ∑ ∣ S ∣ , q ≤ 1 0 6 , 1 ≤ a i , c ≤ 1 0 9 1 \leq S_i \leq n \leq 10^6, 1\leq \sum |S|,q \leq 10^6, 1 \le a_i,c \le 10^9 1Sin106,1S,q106,1ai,c109

C++实现

#include <bits/stdc++.h>
#define int long long
using namespace std;
struct po{
	int val,x;
	bool operator <(const po& a)const{
		return val<a.val;
	}
}p[1000010];
int s[1000010],a[1000010];
bool cmp(int x, int y){return (a[x]<a[y]);}
bool cmp2(po a, po b){return a.x<b.x;}
signed main(){
	int n,c,q;
	cin>>n>>c>>q;
	for (int i=1;i<=n;i++){
		cin>>p[i].val;
		p[i].x=i;
	}
	sort(p+1,p+1+n);//排序
	for (int i=1;i<=n;i++) a[p[i].x]=i; // 存排名
	sort(p+1,p+1+n,cmp2);
	while (q--){
		int k;cin>>k;
		for (int i=1;i<=k;i++) cin>>s[i];
		sort(s+1,s+1+k,cmp); // 按a_i从小到大
		int ans=0;
		for (int i=2;i<=k;i++){
			ans+=p[s[i-1]].val-2*p[s[i]].val+c;
		}
		cout<<ans<<endl;
	}
	return 0;
}

在这里插入图片描述

后续

接下来我会不断用C++来实现信奥比赛中的算法题、GESP考级编程题实现、白名单赛事考题实现,记录日常的编程生活、比赛心得,感兴趣的请关注,我后续将继续分享相关内容

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值