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

来源:互联网 发布:Buffer cache linux 编辑:程序博客网 时间:2024/06/07 16:26

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

题意比较难懂:   给你一个无穷项等差序列, 有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;}


0 0
原创粉丝点击