CodeForces 371C & CodeForces 343C 二分

CodeForces 371C & CodeForces 343C

題目

CF 371C
CF 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去找到最好的時間,而答案和移動的距離又是正相關的,那麼可以考慮一下二分答案,然後去驗證一下。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章