codeforces-#655-D

codeforces-#655-D

七月 14, 2020

D. Omkar and Circle

题意

n(奇数)个数排成一个⚪ 首尾相接

现在反复进行一种操作

取出一个数 然后它两侧的数相加成为新的数

最后只剩1个数

问这个数最大多少

题解

首先想到贪心的两种策略

1.尽量保留最大的

2.尽量让多个数相加留到最后

比如7个数

a b c d e f g

假设最后剩下的数为x

它最多由原先4个数相加最少由原先2个数相加

而这四个数是从⚪的某个位置切断形成链后间隔取到的

推广到n个数形成的⚪ 最少由(n-1)/2个数相加 最少由2个数相加

若想让x是n个数中y个数相加 {y<(n-1)/2}

那它一定是(n-1)/2个数相加的中的某种情况去掉一些数得到的

比如7个数

a b c d e f g

选择最终x由三个数相加得到

去掉b得到 a+c d e f g

去掉f得到 a+c d e+g

去掉e+g 得到 a+c+d

实际上它是 a+c+d+f 的和去掉f

a+c+d+f是去掉b,e,g得到的结果

所以得出结论贪心策略是留下尽量多的数相加

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
#include <bits/stdc++.h>
using namespace std;
typedef long long ll;
#define endl '\n'
#define Turnoff std::ios::sync_with_stdio(false)
typedef pair<ll,ll> P;

const int mod=2e3;
const int Max=4e5+5;
ll data[Max];

int main(){
Turnoff;
int n;cin>>n;
ll ans=0,sum=0;
for(int i=0;i<n;i++){
cin>>data[i];
data[i+n]=data[i];
}
if(n==1){
cout<<data[0]<<endl;
return 0;
}

sum=0;ll temp=0;bool flag=0;
int L=0;
for(int i=0;i<2*n;i++){
sum+=data[i];
if((i&1)==flag){
temp+=data[i];
}
if(i-L+1>=n){
ans=max(ans,temp);
temp=sum-temp;
flag=!flag;
sum-=data[L];
L++;
}
}
cout<<ans<<endl;
return 0;
}