题目链接:http://codeforces.com/contest/1165/problem/F2
题意:n种物品需要购买,每种物品需要购买a[i]件,每件物品价格为2bourle,有m次优惠活动(di,ti):第di天物品ti价值优惠为1bourle
每天可以得到1bourle,求买完所有物品的最少天数。
思路:设所有物品数量为cnt,最少天数一定在[cnt,2 * cnt]之间,因为获得的物品数目随天数是递增的,所以二分找最优解
#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cstring>
#include <map>
#include <set>
#include <vector>
#include <string>
#include <cmath>
#include <queue>
#define rep(i, s, e) for(int i = s; i < e; ++i)
#define lson l, m, rt << 1
#define rson m + 1, r, rt << 1 | 1
#define P pair<int, int>
#define INF 0x3f3f3f3f
#define Mod 998244353
using namespace std;
typedef long long ll;
static const int N = 1005;
static const int MAX_N = 2e5 + 5;
int a[MAX_N], b[MAX_N];
vector<int>vec[MAX_N << 1];
int n;
bool judge(int x, int cnt, vector<int>vec[]){
int day = x; //花费天数(即可花费的bourle,因为每天可获得1bourle)
for(int i = 1; i <= n; ++i) b[i] = a[i];
int cur = 0;
for(int i = x; i >= 1; --i){ //x天的优惠活动
for(int j = 0; j < vec[i].size(); ++j){
int t = vec[i][j];
while(b[t] && day){ //尽可能多的在优惠中购买物品
--b[t];
--cnt; //物品总数
--day; //bourle数量减少
}
}
while(day >= i) ++cur, --day; //borcle数目不能超过天数,多余部分只能用于未参与优惠的物品(这里条件控制的比较好,用if也行)
}
return cur >= 2 * cnt; //未参与优惠的物品需2bourle
}
void solve(){
// freopen("input.txt", "r", stdin);
// freopen("output.txt", "w", stdout);
//ios::sync_with_stdio(false);
int m;
while(scanf("%d%d", &n, &m) != EOF){
int cnt = 0;
for(int i = 0; i < (MAX_N << 1); ++i) vec[i].clear();
for(int i = 1; i <= n; ++i){
scanf("%d", &a[i]);
cnt += a[i];
}
for(int i = 0; i < m; ++i){
int u, v;
scanf("%d%d", &u, &v);
vec[u].push_back(v);
}
int l = cnt, r = cnt << 1;
int ans = 0;
while(l <= r){
int m = l + r >> 1;
if(judge(m, cnt, vec)){
r = m - 1;
ans = m;
}
else l = m + 1;
}
printf("%d\n", ans);
}
}
int main() {
solve();
return 0;
}