闯关「掘金日新计划 · 12 月更文挑战」

178 阅读2分钟

开启掘金成长之旅!这是我参与「掘金日新计划 · 12 月更文挑战」的第28天,点击查看活动详情

闯关

题目描述

某综艺频道推出了一个闯关活动。

活动一共包含 n 个关卡(编号 1∼n),其中 m 个关卡为特殊关卡。

每个关卡都有一个通关分数,其中第 i 个关卡的通关分数为 ai。

挑战者可以自由决定所有关卡的具体挑战顺序,并且每通过一个关卡就可以获得该关卡的通关分数。

值得注意的是,当挑战者即将挑战的关卡是特殊关卡时,如果挑战者当前已经获得的总分数大于该特殊关卡的通关分数,则挑战者可以对该关卡的通关分数进行一次修改,修改后的新分数不能小于原分数,也不能大于挑战者当前已经获得的总分数。

请你计算并输出挑战者通过所有关卡获得的总分数的最大可能值。

输入格式

第一行包含两个整数 n,m。

第二行包含 n 个整数 a1,a2,…,an,表示每个关卡的通过分数。

第三行包含 m 个整数 b1,b2,…,bm,表示每个特殊关卡的编号。

输出格式

一个整数,表示挑战者通过所有关卡获得的总分数的最大可能值。

保证最终答案不超过 2_64−1。

数据范围

前 4 个测试点满足 1≤n≤4。
所有测试点满足 1≤n,m≤100,m≤min(n,30),1≤ai≤107,1≤bi≤n,bi 两两不同。

输入样例1:

4 1
1 3 7 5
3

输出样例1:

18

输入样例2:

3 2
10 3 8
2 3

输出样例2:

40

输入样例3:

2 2
100 200
1 2

输出样例3:

400

输入样例4:

1 1
1
1

输出样例4:

1

思路

其实这个题就是个贪心加模拟的过程,因为不需要按顺序通过关卡,所以最贪心的方法其实就是把所有普通关卡都过完,然后再比较特殊关卡的大小,首先过掉特殊关卡分值最高的,这样能保证把所有其他的关卡都以最高分过掉,然后就是用一个东西来存储特殊关卡的数值或者其他出现的位置就可以啦。

代码

#include<bits/stdc++.h>
using namespace std;
#define int long long
#define IOS ios::sync_with_stdio(false),cin.tie(0),cout.tie(0)
const int N=1e8+10;
int a[N];
map<int,int>b;
signed main(){
    IOS;
    int n,m;
    cin>>n>>m;
    int sum=0;
    for(int i=1;i<=n;i++)cin>>a[i];
    for(int i=1;i<=m;i++){
        int x;
        cin>>x;
        b[x]=1;
    }
    for(int i=1;i<=n;i++){
        if(b[i]!=1)sum+=a[i];
    }
    int maxn=0;
    for(int i=1;i<=n;i++){
        if(b[i]!=0&&a[i]>maxn)maxn=a[i];
    }
    if(sum>=maxn)sum=sum*pow(2,m);
    else{
        sum+=maxn;
        sum=sum*pow(2,m-1);
    }
    cout<<sum<<endl;
    return 0;
}