初看题目,感觉就是道水题,判一下奇偶性就行
考完了才知道,浙江的题嘿嘿
结果最后模拟赛只拿了20。。。
题解:
二分答案,check的时候DP,设
Max[i]
M
a
x
[
i
]
为第i个人最多和第1个人勋章相同的个数,
Min[i]
M
i
n
[
i
]
为第i个人最少和第1个人勋章相同的个数
于是就有
- Max[i]=min(a[i],a[1]−Min[i−1]) M a x [ i ] = m i n ( a [ i ] , a [ 1 ] − M i n [ i − 1 ] )
- Min[i]=max(0ll,a[i]−(t−(a[1]+a[i−1]−Max[i−1]))) M i n [ i ] = m a x ( 0 l l , a [ i ] − ( t − ( a [ 1 ] + a [ i − 1 ] − M a x [ i − 1 ] ) ) )
判一下
Min[n]
M
i
n
[
n
]
是否为0,就结束了…
洛谷的题解貌似有
O(n)
O
(
n
)
的做法,不过我没看懂
#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int MAXN = 30001;
int a[MAXN], n;
int Max[MAXN], Min[MAXN];
inline int read(){
int k = 0, f = 1; char ch = getchar();
while(ch < '0' || ch > '9'){if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9'){k = k*10 + ch - '0'; ch = getchar();}
return k * f;
}
bool check(int t){
memset(Max, 0, sizeof(Max));
memset(Min, 0x3f, sizeof(Min));
Max[1] = Min[1] = a[1];
for(int i = 2; i <= n; i++){
Max[i] = min(a[i], a[1] - Min[i - 1]);
Min[i] = max(0, a[i] - (t - (a[1] + a[i - 1] - Max[i - 1])));
}
return Min[n] == 0;
}
int main(){
n = read();
int l = 0, r = 0, mid;
for(int i = 1; i <= n; i++){
a[i] = read();
r += a[i];
}
a[n + 1] = a[1];
while(l <= r){
mid = (l + r) >> 1;
if(check(mid)) r = mid - 1;
else l = mid + 1;
}
for(int i = 1; i <= n; i++){
l = max(l, a[i] + a[i + 1]);
}
printf("%d", l);
return 0;
}