二分答案+判定

1. 洛谷P3407 散步

Code

  1 #pragma warning (disable:4996)
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <iomanip>
  5 #include <cstring>
  6 #include <string>
  7 #include <cstdio>
  8 #include <queue>
  9 #include <stack>
 10 #include <cmath>
 11 #include <map>
 12 using namespace std;
 13 typedef long long ll;
 14 #define MS(x) memset(x,0,sizeof(x));
 15 #define inf 0x3f3f3f3f
 16 #define Lson(x) x<<1
 17 #define Rson(x) x<<1|1
 18 const int maxn = 1e6 + 5;
 19 
 20 inline int read() {
 21     int x = 0, f = 1;
 22     char ch = getchar();
 23     while (ch<'0' || ch>'9') {
 24         if (ch == '-')
 25             f = -1;
 26         ch = getchar();
 27     }
 28     while (ch >= '0' && ch <= '9') {
 29         x = (x << 1) + (x << 3) + (ch ^ 48);
 30         ch = getchar();
 31     }
 32     return x * f;
 33 }
 34 
 35 inline void write(int x)
 36 {
 37     char F[200];
 38     int tmp = x > 0 ? x : -x;
 39     if (x < 0)putchar('-');
 40     int cnt = 0;
 41     while (tmp > 0)
 42     {
 43         F[cnt++] = tmp % 10 + '0';
 44         tmp /= 10;
 45     }
 46     while (cnt > 0)putchar(F[--cnt]);
 47 }
 48 
 49 ll D[50005];
 50 ll ans;
 51 ll L;
 52 int N, M;
 53 
 54 bool jugde(ll minLenth)
 55 {
 56     int count = 0;
 57     bool flag = true;
 58     for (size_t i = 1, now = 0; i <= N + 1; i++)
 59     {
 60         if (D[i] - D[now] < minLenth)
 61         {
 62 //            cout << D[i] - D[now] << ends;
 63             count++;
 64         }
 65         else
 66             now = i;
 67         //cout << i << ends;
 68         if (count > M)
 69         {
 70             flag = false;
 71 //            cout << "true";
 72             break;
 73         }
 74     }
 75 //    cout << endl;
 76     return flag;
 77 }
 78 
 79 int main()
 80 {
 81     L = read();
 82     N = read();
 83     M = read();
 84     for (size_t i = 1; i <= N; i++)
 85         D[i] = read();
 86     D[N + 1] = L;
 87     ll left = 1;
 88     ll right = L;
 89     while (left < right)
 90     {
 91         ll mid = (left + right + 1) >> 1;
 92         if (jugde(mid))
 93             left = mid;
 94         else
 95             right = mid - 1;
 96         cout << left << ends << mid << ends << right << endl;
 97     }
 98     ans = left;
 99     write(ans);
100     cout << endl;
101     return 0;
102 }
Binary Search

2. 洛谷P2678 跳石头:P2678的题解有个大佬讲的很好,忘可自查

Code

 

  1 #pragma warning (disable:4996)
  2 #include <algorithm>
  3 #include <iostream>
  4 #include <iomanip>
  5 #include <cstring>
  6 #include <string>
  7 #include <cstdio>
  8 #include <queue>
  9 #include <stack>
 10 #include <cmath>
 11 #include <map>
 12 using namespace std;
 13 typedef long long ll;
 14 #define MS(x) memset(x,0,sizeof(x));
 15 #define inf 0x3f3f3f3f
 16 #define Lson(x) x<<1
 17 #define Rson(x) x<<1|1
 18 const int maxn = 1e6 + 5;
 19 
 20 inline int read() {
 21     int x = 0, f = 1;
 22     char ch = getchar();
 23     while (ch<'0' || ch>'9') {
 24         if (ch == '-')
 25             f = -1;
 26         ch = getchar();
 27     }
 28     while (ch >= '0' && ch <= '9') {
 29         x = (x << 1) + (x << 3) + (ch ^ 48);
 30         ch = getchar();
 31     }
 32     return x * f;
 33 }
 34 
 35 inline void write(int x)
 36 {
 37     char F[200];
 38     int tmp = x > 0 ? x : -x;
 39     if (x < 0)putchar('-');
 40     int cnt = 0;
 41     while (tmp > 0)
 42     {
 43         F[cnt++] = tmp % 10 + '0';
 44         tmp /= 10;
 45     }
 46     while (cnt > 0)putchar(F[--cnt]);
 47 }
 48 
 49 ll D[50005];
 50 ll ans;
 51 ll L;
 52 int N, M;
 53 
 54 bool jugde(ll minLenth)
 55 {
 56     int count = 0;
 57     bool flag = true;
 58     for (size_t i = 1, now = 0; i <= N + 1; i++)
 59     {
 60         if (D[i] - D[now] < minLenth)
 61         {
 62 //            cout << D[i] - D[now] << ends;
 63             count++;
 64         }
 65         else
 66             now = i;
 67         //cout << i << ends;
 68         if (count > M)
 69         {
 70             flag = false;
 71 //            cout << "true";
 72             break;
 73         }
 74     }
 75 //    cout << endl;
 76     return flag;
 77 }
 78 
 79 int main()
 80 {
 81     L = read();
 82     N = read();
 83     M = read();
 84     for (size_t i = 1; i <= N; i++)
 85         D[i] = read();
 86     D[N + 1] = L;
 87     ll left = 1;
 88     ll right = L;
 89     while (left < right)
 90     {
 91         ll mid = (left + right + 1) >> 1;
 92         if (jugde(mid))
 93             left = mid;
 94         else
 95             right = mid - 1;
 96 //        cout << left << ends << mid << ends << right << endl;
 97     }
 98     ans = left;
 99     write(ans);
100     cout << endl;
101     return 0;
102 }
Binary Search

3. POJ3974:学哈希时遇到的一道马拉车模板题->[O(n)],可以用“哈希+二分”->[O(nlogn)]

(听说哈希和二分很配?)(´ー∀ー`)

4. POJ2018 / 洛谷P1404

Solve

求连续子段的最大平均数,要求长度不小于L

 —>二分答案,判定“是否存在一个长度不小于L的子段,平均值不小于二分的值”

 —>数列每个元素减去二分值,判定“是否存在一个长度不小于L的子段,子段和非负”

 —>求一个长度不小于L的最大子段和(@《最大子序列》

(TIPS:由于平均数为double类型,所以二分while需要配置EPS = 1e-5之类,注意数据类型)(另外之前在while里MS()TLE了🙈,罪过)

Code

 1 #pragma warning (disable:4996)
 2 #include <algorithm>
 3 #include <iostream>
 4 #include <iomanip>
 5 #include <cstring>
 6 #include <string>
 7 #include <cstdio>
 8 #include <queue>
 9 #include <stack>
10 #include <cmath>
11 #include <map>
12 #include <set>
13 using namespace std;
14 typedef long long ll;
15 #define MS(x) memset(x,0,sizeof(x))
16 #define inf 0x3f3f3f3f
17 const int maxn = 1e6 + 10;
18 
19 double n[maxn];
20 double initn[maxn];//将每个原区间元素都减去二分值
21 double sum[maxn] = { 0 };//求区间和一般用前缀和相减
22 
23 int main()
24 {
25     int N, F;
26     scanf("%d %d", &N, &F);
27     for (int i = 1; i <= N; i++)
28         scanf("%lf", &n[i]);
29     double eps = 1e-5;
30     double l = 0, r = 1e6;
31     while (r - l > eps)
32     {
33         double mid = (l + r) / 2;
34         for (int i = 1; i <= N; i++)
35             initn[i] = n[i] - mid;
36         for (int i = 1; i <= N; i++)
37             sum[i] = sum[i - 1] + initn[i];
38         double ans = -0x7f7f7f7f;
39         double mi = 0x7f7f7f7f;
40         for (int i = F; i <= N; i++)//以后常看看呀~
41         {
42             mi = min(sum[i - F], mi);
43             ans = max(ans, sum[i] - mi);
44         }
45         if (ans >= 0)
46             l = mid;
47         else
48             r = mid;
49     }
50     printf("%d", int(r * 1000));
51     return 0;
52 }
二分

 

posted @ 2019-08-18 18:04  吴下阿萌  阅读(328)  评论(0)    收藏  举报