题意:这个人的运动方式类似于77C - Beavermuncher-0xFF 求最后最多可以走过的点。
做法:假设一个人最后回到j,最多可以走过的点,可以先求出i-0-i,i-n-i,最多可以走过的点数,这个可以用直接贪心,设在把i-n之间的桥都走塌陷的情况下可以做过最多的点
还可以求出0-i(不经过两点范围之外的点)最多可以做过的点 sum[i]。
然后dp[j]=sum[j]-sum[i]+left[j]+right[i]=sum[j]+left[j]+left[i]-sum[i],这个可以用单调队列记录
这种题目首先要暴力枚举出发点和终点,然后在判断走回路和不走回路的情况。这里的运动是可以归类的,千万不要被一开始看似无需的情况搞晕啊》。。。
#include<vector>
#include<algorithm>
#include<cstdio>
#include<cstring>
#include<queue>
#define LL long long
const int LMT=100005;
using namespace std;
LL lef[LMT],rig[LMT],sum[LMT],bri[LMT];
struct comp
{
bool operator()(const int i, const int j)
{
return lef[i]-sum[i]<lef[j]-sum[j];
}
};
priority_queue<int,vector<int>,comp> que;
int main(void)
{
int n;LL ans=0;
scanf("%d",&n);
for(int i=1;i<n;i++)
{
scanf("%I64d",&bri[i]);
if(bri[i]>=2)lef[i]+=lef[i-1];
lef[i]+=bri[i]&1?bri[i]-1:bri[i];
sum[i]+=sum[i-1]+(bri[i]&1?bri[i]:bri[i]-1);
}
for(int i=n-1;i>=0;i--)
{
rig[i]+=bri[i+1]&1?bri[i+1]-1:bri[i+1];
if(bri[i+1]>=2)rig[i]+=rig[i+1];//靠!!
}
for(int i=0;i<n;i++)
{
que.push(i);
ans=max(ans,lef[que.top()]-sum[que.top()]+sum[i]+rig[i]);
}
printf("%I64d\n",ans);
return 0;
}