Acwing102 最佳牛围栏 (简单二分)

首先:  (1):   这个*1000的操作肯定是为了防止出现double,这样的话都是整数,好操作!!!!!!

(2):  这个首先从暴力方向来想,我们要知道这个的值的话,我们的方法好像只有枚举所有大于等于F的区间来进行操作,但是这样的复杂度是O(N^2-F^2),这个可以等效看作是N^2的,只要数据稍微大一点点,这个算法就会被卡掉

(3): 然后这个可以接受的数据范围是Nlog(N)的?

(4): 每块地的平均值最大?   那么这个函数肯定是单调递增的,我们可以二分一个值来验证,看看这个值是不是符合规则的,如果符合规则,再二分更大的范围,如果这个值大了的话,就继续往小的值的方向走,如果合适的话就看能不能变大点。

(5):这个不是重点,二分的重点是我们想怎么去check这个值。二分+验证

(6):   二分+验证(这里面最重要是验证,怎么把一个直接求值的问题转换成验证性问题,这个是重中之重)(二分的话我们有时候也会碰到一些单调性很难证明或者单调性直接就是萎了的算法)

(7):   我们考虑一下怎么来做这倒题,首先转化成一个二分问题,哪我们怎么来验证?怎么来check呢》?????   不可能对每个端再枚举然后相减把,这样除了多了个log外没有任何用处

(8):   我们二分的是最后的答案,那对这个答案我们可以怎么操作呢。我们二分的是这个平均值mid ,这个显然可以知道 有  sum[i]-sum[j-1]-(i-j+1)*mid 我们发现这样不好搞,把每个num[i]减去mid,这个就可以把mid放进sum里面去。就可以得到我们最后的答案了。

下面是代码:

 1 #include <cstdio>
 2 #include <cstring>
 3 #include <algorithm>
 4 #include <iostream>
 5 #include <cmath>
 6 #include <bitset>
 7 typedef long long ll;
 8 using namespace std;
 9 const int maxn=101000;
10 ll num[maxn],sum[maxn],ai[maxn];
11 int n,f;
12 ll lb=1000,rb=1,ans=0;
13 // sum[i]-sum[j-1] > 0    说明至少能有这么多
14 bool check(ll mid){
15     sum[0]=0;
16     for(int i=1;i<=n;i++) ai[i]=num[i]-mid;
17     for(int i=1;i<=n;i++) sum[i]=sum[i-1]+ai[i];
18     ll minn=sum[0];
19     for(int i=f;i<=n;i++){
20         if(sum[i]>=minn) return true;
21         minn=min(sum[i-f+1],minn);
22     }
23     return false;
24 }
25
26 int main(){
27     scanf("%d%d",&n,&f);
28     for(int i=1;i<=n;i++){scanf("%lld",&num[i]);num[i]=num[i]*1000;rb+=num[i];}
29     while(lb<=rb){
30         ll mid=(lb+rb)/2;
31         if(check(mid)){
32             ans=mid;
33             lb=mid+1;
34         }else rb=mid-1;
35     }
36     printf("%lld\n",ans);
37     return 0;
38 }

原文地址:https://www.cnblogs.com/pandaking/p/12031025.html

时间: 2024-11-05 22:04:37

Acwing102 最佳牛围栏 (简单二分)的相关文章

最佳牛围栏

题目链接 题意 把一个长度为N的序列取出一段长度不小于F的子段,求平均值最大的子段的平均值. 思路 答案似乎不容易看出单调性... 换个思路, 一段序列减去平均值后得到的序列, 序列和一定为0. 如果减去的值小于平均值, 则序列和为正, 反之为负. 可以二分一个值, 然后减去这个值, 如果序列中长度不小于F的最大子段和为正, 说明平均值可以再大一些.. 单调性就可以看出来了: 二分值越大, 序列所有数减去二分值后得到的最大子段段和就越小. 关键便是快速判断最大子段和. 代码 #include<i

P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold 解题报告

P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold 题意 给一个字符串,每次可以从两边中的一边取一个字符,要求取出的字符串字典序最小 可以Hash+二分 也可以SA 首先贪心选字典序小的 然后遇到相等的了比Rank数组,把原串倍长一下就可以比了. Code: #include <cstdio> #include <algorithm> const int N=6e4+10; char s[N],ans[N]; int sa[N],Rank[N]

贪心 洛谷P2870 [USACO07DEC]最佳牛线,黄金Best Cow Line, Gold

[USACO07DEC]最佳牛线,黄金Best Cow Line, Gold 题目描述 FJ is about to take his N (1 ≤ N ≤ 30,000) cows to the annual"Farmer of the Year" competition. In this contest every farmer arranges his cows in a line and herds them past the judges. The contest organ

HDU 2119 Matrix 简单二分匹配

行做x集,列做y集,1就给该行该列连一条边,输出最大匹配边即可 #include<cstdio> #include<cstring> #include<algorithm> #include<iostream> #include<vector> #include<set> using namespace std; #define N 105 int lef[N], pn;//lef[v]表示Y集的点v 当前连接的点 , pn为x点集的

poj 3273 Monthly Expence 简单二分

1 /** 2 大意: 有连续的n天,每一天有一定的花费,将其分成m份,每一份占一天或者连续的几天,求这m份中的最大值 3 思路: 二分其最大上限,看在此最大上线,能分成多少份,若大于m份,说明上限过小,需要扩大上限 4 若小于m份,则说明,下限过大,需要缩小上限. 5 **/ 6 #include <iostream> 7 8 using namespace std; 9 int c[100010]; // 记录,每天的花费 10 int main() 11 { 12 int n,m; 13

poj 2785 4 Values whose Sum is 0 (简单二分)

//每列选一个数相加为0的个数 # include <stdio.h> # include <algorithm> # include <string.h> using namespace std; int ab[4010*4010],cd[4010*4010]; int main() { int n,i,k,j,count,a[4010],b[4010],c[4010],d[4010]; while(~scanf("%d",&n)) { f

[Luogu2870] [USACO07DEC]最佳牛线Best Cow Line(贪心+后缀数组)

[Luogu2870] [USACO07DEC]最佳牛线Best Cow Line(贪心+后缀数组) 题面 FJ打算带他的\(N(1 \leq N \leq 30,000)\)头奶牛去参加一年一度的"全美农场主大奖赛".在这场比赛中,每个参赛者都必须让他的奶牛排成一列,然后领她们从裁判席前依次走过. 今年,竞赛委员会在接受队伍报名时,采用了一种新的登记规则:他们把所有队伍中奶牛名字的首字母取出,按它们对应奶牛在队伍中的次序排成一列(比如说,如果FJ带去的奶牛依次为Bessie.Sylv

hdu-4185.loiol_skimming(简单二分匹配模型)

1 /************************************************************************* 2 > File Name: hdu-4185.oil_skimming.cpp 3 > Author: CruelKing 4 > Mail: [email protected] 5 > Created Time: 2019年09月03日 星期二 09时12分12秒 6 本题思路:简单分析过后就可以知道如果一点a被另一个点b匹配

hdu4190 简单二分

题意是 有n个城市,m个投票箱,接下来n个城市人口数,每个投票箱都不能为空,计算最后投票箱的容量必须达到多少,才能满足需要. 每个城市的人必须只能将票投到自己城市分得得投票箱中.要是容量最小箱子必须得都用上 二分枚举所以的人数 #include<stdio.h> #include<string.h> #include<iostream> using namespace std; int num[500100],n,m; int judge(int x) { int s=