Codeforces Round #299 (Div. 1) A. Tavas and Karafs(二分)

该题数据量很大, 需要用二分加速算法。

题意比较难懂:   给你一个无穷项等差序列, 有n个查询,  对于每个查询, 有三个数 l, t, m, 每次从第l个数之后的数种选择最多m个数使得他们的值减一, 经过最多t次, 求一个最大的r, 使得从l到r所有数都减为0。

显然这是一个递增序列, 那么我们直接二分答案就行了 。 如果满足这段序列求和 <= t*m 并且 a[r] < t,那么这个答案就是正确的 (YY一下,容易证明)。

另外还学到了一个二分上界的好姿势。

细节参见代码:

#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<string>
#include<vector>
#include<stack>
#include<bitset>
#include<cstdlib>
#include<cmath>
#include<set>
#include<list>
#include<deque>
#include<map>
#include<queue>
#define Max(a,b) ((a)>(b)?(a):(b))
#define Min(a,b) ((a)<(b)?(a):(b))
using namespace std;
typedef long long ll;
const double PI = acos(-1.0);
const double eps = 1e-6;
const int INF = 1000000000;
const int maxn = 100;
ll T,n,m,l,t,A,B;
ll sum(ll mid) {
    ll v = A*mid + mid*(mid-1)/2*B;
    ll u = A*(l-1) + (l-1)*(l-2)/2*B;
    return v - u;
}
int main() {
    while(~scanf("%I64d%I64d%I64d",&A,&B,&n)) {
        while(n--) {
            scanf("%I64d%I64d%I64d",&l,&t,&m);
            if(sum(l) > t) { printf("-1\n"); continue; }
            ll R = l+t, L = l, mid;
            while(R >= L) {
                mid = (R+L)/2;
                if(sum(mid) <= t*m && A + (mid-1)*B <= t) L = mid + 1;
                else R = mid-1;
            }
            printf("%I64d\n",L-1);
        }
    }
    return 0;
}





你可能感兴趣的:(codeforces,二分)