二分答案+判定
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 }
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 }
3. POJ3974:学哈希时遇到的一道马拉车模板题->[O(n)],可以用“哈希+二分”->[O(nlogn)]
(听说哈希和二分很配?)(´ー∀ー`)
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 }
浙公网安备 33010602011771号