CodeForces 371C & CodeForces 343C
題目
思路
二分答案,主要是judge的代碼要想好怎麼寫
371C二分答案直接看是否合適
343C二分答案,pos記錄最小未被覆蓋的點的下標,然後兩種方法,1.貪心先左到pos,2.貪心向右走到(mid - (h[i] - pos[i]))/2再向左走,因爲這樣保證能到達pos的位置,最後取向右走的最大值然後二分找下一個pos
代碼
371C
#include <iostream>
#include <cstdio>
#include <set>
#include <list>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <sstream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <fstream>
#include <iomanip>
//#include <unordered_map>
using namespace std;
#define dbg(x) cerr << #x " = " << x << endl;
typedef pair<int, int> P;
typedef long long ll;
#define FIN freopen("in.txt", "r", stdin);
string op;
int main()
{
// FIN;
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
int nb, ns, nc, pb, ps, pc;
cin >> op;
cin >> nb >> ns >> nc >> pb >> ps >> pc;
int b = 0, s = 0,c = 0;
ll p;
cin >> p;
for(int i = 0; i < op.size(); i++)
{
if(op[i] == 'B') b++;
if(op[i] == 'S') s++;
if(op[i] == 'C') c++;
}
ll l = 0;
ll r = 2e12;
ll ans ;
while(l < r)
{
//dbg(l);
//dbg(r);
ans = (l + r) >> 1;
ll resb = b * ans - nb;
ll ress = s * ans - ns;
ll resc = c * ans - nc;
//cout << resb << ' ' << ress << ' ' << resc <<endl;
ll tot = max(resb, 0LL) * pb + max(resc, 0LL) * pc + max(ress, 0LL) * ps;
//dbg(tot);
if(tot > p)
{
r = ans;
}
else
{
l = ans + 1;
}
}
cout << l - 1 << endl;
}
343C
#include <iostream>
#include <cstdio>
#include <set>
#include <list>
#include <vector>
#include <stack>
#include <queue>
#include <map>
#include <string>
#include <sstream>
#include <algorithm>
#include <cstring>
#include <cstdlib>
#include <cctype>
#include <cmath>
#include <fstream>
#include <iomanip>
//#include <unordered_map>
using namespace std;
#define dbg(x) cerr << #x " = " << x << endl;
typedef pair<int, int> P;
typedef long long ll;
#define FIN freopen("in.txt", "r", stdin);
const int MAXN = 1e5+5;
ll h[MAXN];
ll p[MAXN];
int n, m;
int judge(ll mid)
{
ll pos = 0;
for(int i = 0; i < n; i++)
{
ll x= mid;
if(h[i] >= p[pos])
{
if(mid >= h[i] - p[pos])
{
x = max(0LL, max(mid - 2 * (h[i] - p[pos]), (mid - h[i] + p[pos]) / 2));
}
else
return 0;
}
pos = upper_bound(p, p + m, x + h[i]) - p;
if(pos == m) return 1;
}
return 0;
}
int main()
{
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin >> n >> m;
for(int i = 0; i < n ; i++)
{
cin >> h[i];
}
for(int i = 0; i < m; i++)
{
cin >> p[i];
}
ll l = 0, r = 1e12;
ll mid;
ll ans = 0;
while(l < r)
{
mid = (l + r) >> 1;
if(judge(mid))
{
r = mid;
}
else
{
l = mid + 1;
}
}
cout << r << endl;
}
總結
什麼時候能使用二分答案,這是思考的重點,看起來應該是如果無法用特殊的辦法求出答案,每一種答案都需要暴力來驗證細節,驗證答案的準確性,比如371C我們無法通過暴力去找到合適的漢堡數量,而價格和答案又有正相關的關係,再例如343C中,我們無法bfs去找到最好的時間,而答案和移動的距離又是正相關的,那麼可以考慮一下二分答案,然後去驗證一下。