时隔快1个月才回来看这个G题,刚打的时候感觉做出来人的数量很少就没打算看,其实,这是一个思维一维dp,首先,我们把dp[i]表示前i个选i/2
个求和的最大值。 然后我们分俩种情况来看其状态转移,第一种序列下标是奇数的情况他的值是由前一个下标的dp值和前2个下标的dp值+a[当前下标值]取最大值转移过来的,最奇妙的是下标为偶数的情况,因为题中说明不能选相邻的数,所以当我们的下标是偶数时候,我们不选当前值,就是
由从1到当前值区间内所有奇数的和来转移过来,这样我们可以用一个前缀和数组,来统计所有奇数下标的和,这个题就完美解决啦~
因为x必选所以让其加上一个比较大的值,最后还是可以从总值中减去的
下面请看代码把

#include<bits/stdc++.h>
const int maxn = 2e5+10;
long long dp[maxn],n,x,sum[maxn],a[maxn];
//dp代表从1~i选i/2个元素的最大值
//sum来统计下标为奇数的前缀和
//a代表原来序列的值 
using namespace std;
int main()
{
    ios::sync_with_stdio(false);
    cin.tie(0);cout.tie(0);
    cin>>n>>x;
    for(int i=1;i<=n;i++) cin>>a[i];
    a[x]+=1e14;//因为x是必选所以让x加上一个较大的值 
    sum[1]=a[1];
    //前缀和数组也方便对dp进行赋初值 
    for(long long i=3;i<=n;i+=2)
    {
        sum[i]=sum[i-2]+a[i];
    } 
    for(long long i=2;i<=n;i++)//从第二个点开始dp 
    {
        if(i%2)//如果是奇数, 我们可以选之前所有的偶数,也可以选当前所有的奇数 
        {
            dp[i]=max(dp[i-1],dp[i-2]+a[i]);
        }
        else{
            dp[i]=max(sum[i-1],dp[i-2]+a[i]);
        }
    }   //同理我们可以选之前所有的奇数,也可以选当前的所有偶数
    //注意这里的奇数和偶数指的下标 
    dp[n]-=1e14;
    cout<<dp[n]<<endl;
}