【Codeforces Round #299 (Div. 2) C】 Tavas and Karafs

【链接】 我是链接,点我呀:)
【题意】

给你一个规则,让你知道第i根萝卜的高度为si = A+(i-1)*B 现在给你n个询问; 每次询问给你一个固定的起点l; 让你找一个最大的右端点r; 使得l..r这一段能够在t次"m吃操作"内被吃完.

【题解】

如果l..r里面的最大值大于t了;则无解

最大值小于等于t的话.
每次可以取m个。
然后可以取t次。
也就是说
这一段里面的和<=m*t;

只要A+(i-1)*B大于1e6了就停下来
最坏情况就是A和B都为1

写个rmq+二分就好

【代码】

#include <bits/stdc++.h>
using namespace std;
#define ll long long

const int N = 1e6+10;

ll a[N+100],pre[N+100];
ll A,B,Q;
int n;

const int MAXL = 20;//log2�������󳤶�
const int INF = 0x3f3f3f3f;//��ֵ����ֵ�����ֵ

struct abc{
    ll pre2[MAXL+5],need[N+10];
    ll fmax[N+10][MAXL+5];

    void init(int n)
    {
        pre2[0] = 1;
        for (int i = 1;i <= MAXL;i++)
        {
            pre2[i] = pre2[i-1]<<1;
        }
        need[1] = 0; need[2] = 1;
        int temp = 2;
        for (int i = 3; i <= n; i++)//need[i]��ʾ����Ϊi��2�Ķ��ٴη�,�������Ϊ[log2i]
            if (pre2[temp] == i)
                need[i] = need[i - 1] + 1, temp++;
            else
                need[i] = need[i - 1];
    }

    void getst(ll *a,int n)
    {
        for (int i = 1;i <= n;i++)//�±��0��ʼ�͸ijɶ�Ӧ�ľͺ�
            fmax[i][0] = a[i];


        for (int l = 1;pre2[l]<=n;l++)
            for (int i = 1;i <= n;i++){
                if (i+pre2[l]-1<=n)
                    fmax[i][l] = max(fmax[i][l-1],fmax[i+pre2[l-1]][l-1]);
            }
		
    }

    int getmax(int l,int r)
    {
        int len = need[r-l+1];
        return max(fmax[l][len],fmax[r-pre2[len]+1][len]);
    }

}ST;

bool ok(int l,int r,ll t,ll m){
 	if (r > n) return false;
 	int ma = ST.getmax(l,r);
 	if (ma>t) return false;
 	ll ju = t*m;
 	ll sum = pre[r]-pre[l-1];
 	if (sum <= ju){
 	 	return true;
 	}
	return false;

}

int main(){
	#ifdef LOCAL_DEFINE
	    freopen("rush_in.txt", "rt", stdin);
	#endif
	scanf("%lld%lld%lld",&A,&B,&Q);
	for (int i = 1; ;i++){
	 	a[i] = A + (i-1)*B;
	 	if (a[i]>(int)1e6){
	 		n = i-1;
	 	 	break;
	 	}
	}


	ST.init(n);
	ST.getst(a,n);

	for (int i = 1;i <= n;i++){
		pre[i] = pre[i-1] + a[i];
	}
	
	while (Q--){
		int l;
		ll t,m;
		scanf("%d%lld%lld",&l,&t,&m);

		if (l > n){
			puts("-1");
			continue;
		}
		int L = l,R = N+10,temp = -1;
		while (L<=R){
		 	int mid = (L+R)>>1;
		 	if (ok(l,mid,t,m)){
				temp = mid;
				L = mid+1;		 	 	
		 	}             else{
		 	 	R = mid-1;
		 	}
		}
		printf("%d\n",temp);
	}
	return 0;
}
posted @ 2017-11-07 19:42  AWCXV  阅读(186)  评论(0编辑  收藏  举报