C. Fragile Bridges
题目连接:
http://codeforces.com/contest/201/problem/C
Description
You are playing a video game and you have just reached the bonus level, where the only possible goal is to score as many points as possible. Being a perfectionist, you've decided that you won't leave this level until you've gained the maximum possible number of points there.
The bonus level consists of n small platforms placed in a line and numbered from 1 to n from left to right and (n - 1) bridges connecting adjacent platforms. The bridges between the platforms are very fragile, and for each bridge the number of times one can pass this bridge from one of its ends to the other before it collapses forever is known in advance.
The player's actions are as follows. First, he selects one of the platforms to be the starting position for his hero. After that the player can freely move the hero across the platforms moving by the undestroyed bridges. As soon as the hero finds himself on a platform with no undestroyed bridge attached to it, the level is automatically ended. The number of points scored by the player at the end of the level is calculated as the number of transitions made by the hero between the platforms. Note that if the hero started moving by a certain bridge, he has to continue moving in the same direction until he is on a platform.
Find how many points you need to score to be sure that nobody will beat your record, and move to the next level with a quiet heart.
Input
The first line contains a single integer n (2 ≤ n ≤ 105) — the number of platforms on the bonus level. The second line contains (n - 1) integers ai (1 ≤ ai ≤ 109, 1 ≤ i < n) — the number of transitions from one end to the other that the bridge between platforms i and i + 1 can bear.
Output
Print a single integer — the maximum number of points a player can get on the bonus level.
Please, do not use the %lld specifier to read or write 64-bit integers in С++. It is preferred to use the cin, cout streams or the %I64d specifier.
Sample Input
5
2 1 2 1
Sample Output
5
Hint
题意
有n个点,n-1座桥,每座桥最多通过a[i]次,每通过一次可以获得1分
然后问你怎么选择起点和路线,才能获得最多的分数
题解:
dp
我们想想可以发现,我们令l[i]表示i点向左边走,且最后回到i点最多能得多少分,r[i]表示i点向右走,且最后回到i点最多能得多少分
odd[i]表示,从1号桥开始,走到i号桥,最多能得多少分
显然,我们这道题要求的最大值,应该就是l[i]-odd[i]+r[j]+odd[j]这个东西,使得这个东西最大就好了
我们暴力枚举j,然后每次用set去拿到最大的l[i]-odd[i]就好了
应该叫dp吧,大概 O.O
代码
#include<bits/stdc++.h>
using namespace std;
const int maxn = 1e5+7;
long long l[maxn],r[maxn],odd[maxn];
int n;
long long a[maxn];
int get(int x)
{
if(x%2==1)return x-1;
return x;
}
set<long long>s;
int main()
{
scanf("%d",&n);
for(int i=0;i<n-1;i++)
scanf("%d",&a[i]);
for(int i=1;i<n-1;i++)
if(a[i-1]>1)
l[i]=l[i-1]+get(a[i-1]);
for(int i=n-2;i>=0;i--)
if(a[i]>1)
r[i]=r[i+1]+get(a[i]);
for(int i=0;i<n-1;i++)
{
odd[i]+=get(a[i]-1)+1;
if(i>0)odd[i]+=odd[i-1];
}
long long ans = l[0]+r[0];
long long tmp = ans;
s.insert(l[0]);
for(int i=1;i<n;i++)
{
s.insert(l[i]-odd[i-1]);
long long p=*--s.lower_bound(1LL*1e16);
ans=max(r[i]+odd[i-1]+p,ans);
}
cout<<ans<<endl;
}