vijos 1894 セチの祈り
题面链接
(题面的背景可以说是非常做作了(来自文科生的嘲笑))
背景
琼花飘落 彩蝶曼舞 又是一年春
满腹愁情 化作伤春酒
梧桐细雨 影影绰绰 残阳落
韶华飞逝 梦断都成空
描述
在 Ninian 的花园里,有许多琼花,环绕着中间的凉亭。
有 N 片琼花,组成一个环。
Ninian 想在凉亭中发动 [セチの祈り] , 需要划分出三个区域的琼花,为了平均,要最大化面积最小的区域的面积。
划分区域:即用三刀把这个环分成三段,每段称之为一个区域。
格式
输入格式
第一行一个整数 N 。
接下来 N 个整数 Si ,表示第 i 片琼花的面积。
输出格式
输出一个整数,面积最小的区域的面积。
样例1
样例输入1
6
1
5
4
5
2
4
样例输出1
6
样例2
样例输入2
30
1
34
44
13
30
1
9
3
7
7
20
12
2
44
6
9
44
31
17
20
33
18
48
23
19
31
24
50
43
15
样例输出2
213
限制
对于 20% 的数据:
3 ≤ N ≤ 400
对于 100% 的数据:
3 ≤ N ≤ 100 000
1 ≤ Ai ≤ 1 000 000 000
来源
布吉岛。
题解
二分+贪心
记录前缀和s
i从0到n扫, 加上末尾的一部分(末尾二分贪心取最大)作为一段
中间的一段二分.
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<cstdlib> 5 #include<set> 6 #include<ctime> 7 #include<vector> 8 #include<cmath> 9 #include<algorithm> 10 #include<map> 11 #define inf 1000000000 12 #define ll long long 13 #define rep(i,a,b) for (int i = a; i <= b; ++ i) 14 using namespace std; 15 const ll MAXN = 100000+10; 16 inline ll read() 17 { 18 ll x=0,f=1;char ch=getchar(); 19 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 20 while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();} 21 return x*f; 22 } 23 24 ll s[MAXN], a[MAXN], n, midans, ans; 25 26 ll findans(ll l, ll r, ll init) { 27 ll mid, ans(-1), R = r; 28 while (l <= r) { 29 mid = (l+r) >> 1; 30 if (s[R] - s[mid-1] + init >= midans) ans = mid, l = mid + 1; 31 else r = mid - 1; 32 } 33 return ans; 34 } 35 36 ll jud() { 37 rep(i,0,n) { 38 ll x = findans(i+1,n,s[i]), 39 y = findans(i+1,x-1,0); 40 if (y == -1 || x == -1) continue; 41 if (s[y-1] - s[i] >= midans) return 1; 42 } 43 return 0; 44 } 45 46 int main() { 47 n = read(); 48 rep(i,1,n) a[i] = read(); 49 rep(i,1,n) s[i] = s[i-1] + a[i]; 50 ll l(0), r(s[n]); 51 while (l <= r) { 52 midans = (l+r) >> 1; 53 if (jud()) ans = midans, l = midans + 1; 54 else r = midans - 1; 55 } 56 printf("%lld",ans); 57 return 0; 58 }