【2015-2016 ACM-ICPC, NEERC, Southern Subregional Contest G】【数据结构-线段树】Hiring 准备时间完成时间最早完成日期

来源:互联网 发布:比价商城源码 编辑:程序博客网 时间:2024/06/07 21:52

G. Hiring
time limit per test
4 seconds
memory limit per test
512 megabytes
input
standard input
output
standard output

The head of human resources department decided to hire a new employee. He created a test exercise for candidates which should be accomplished in at most m working days. Each candidate has to pass this test exercise. During the j-th day a candidate is allowed to be in the office for at most tj units of time.

Overall, n candidates decided to apply for the job and sent out their resumes. Based on data received the head has defined two parameters describing every candidate: di and ri. The parameter di is the time to get prepared for work which the i-th candidate spends each morning. This time doesn't depend on day. The parameter ri is the total working time needed for the i-th candidate to accomplish the whole test exercise.

Thus the time spent in the office in the j-th day consists of di units of time to get prepared and some units of time to proceed with the exercise. A candidate can skip entire working day and do not come to the office. Obviously in this case he doesn't spend di units of time to prepare.

To complete the exercise a candidate should spend exactly ri units of time working on the exercise (time to prepare is not counted here).

Find out for each candidate what is the earliest possible day when he can fully accomplish the test exercise. It is allowed to skip working days, but if candidate works during a day then he must spend di units of time to prepare for work before he starts progressing on the exercise.

Input

The first line contains two integer numbers n,  m (1 ≤ n,  m ≤ 2·105) — the number of candidates and the maximum number of working days to do the test exercise.

The second line contains m integer numbers t1, t2, ..., tm (1 ≤ tj ≤ 106) — the durations of working days in time units.

The following n lines contain two integers each: di,  ri (0 ≤ di ≤ 106,  1 ≤ ri ≤ 106) — how much time in the beginning of a day is required for i-th candidate before he starts his work on the test exercise and how much time it is needed for him to accomplish this task.

Output

Output a sequence of n integer numbers b1, b2, ..., bn, where bi is the earliest day when the i-th candidate can finish the test exercise.

In case the i-th candidate cannot finish the test exercise in m days output bi = 0.

Days in this problem are numbered from 1 to m in the order they are given in the input.

Sample test(s)
input
3 34 2 51 32 53 4
output
1 3 0 


#include<stdio.h>#include<iostream>#include<string.h>#include<ctype.h>#include<vector>#include<map>#include<algorithm>#define ls o<<1#define rs o<<1|1using namespace std;typedef long long LL;const int N=2e5+10;int n,m;int W,V,O;int ans[N];struct A{    int l,r,flag,num,min;    LL sum;}a[1<<19];struct B{    int w,v,o;    bool operator < (const B& b)const    {        return w<b.w;    }}b[N];void pushup(int o){    a[o].sum=a[ls].sum+a[rs].sum;    a[o].num=a[ls].num+a[rs].num;    a[o].min=min(a[ls].min,a[rs].min);}void pushdown(int o){    if(a[o].flag)    {        a[ls].sum-=(LL)a[ls].num*a[o].flag;        a[rs].sum-=(LL)a[rs].num*a[o].flag;        a[ls].flag+=a[o].flag;        a[rs].flag+=a[o].flag;        a[ls].min-=a[o].flag;        a[rs].min-=a[o].flag;        a[o].flag=0;        return;    }}void build(int o,int l,int r){    a[o].l=l;    a[o].r=r;    a[o].flag=0;    if(a[o].l==a[o].r)    {        scanf("%d",&a[o].sum);a[o].num=1;        a[o].min=a[o].sum;        return;    }    int m=(a[o].l+a[o].r)>>1;    build(ls,l,m);    build(rs,m+1,r);    pushup(o);}void del(int o){    if(a[o].l==a[o].r)    {        a[o].sum=0;        a[o].num=0;        a[o].min=1e9;        return;    }    pushdown(o);    if(a[ls].min<=0)del(ls);    if(a[rs].min<=0)del(rs);    pushup(o);}void change(int o,int l,int r){    if(l==a[o].l&&r==a[o].r)    {        a[o].sum-=(LL)W*a[o].num;        a[o].flag+=W;        a[o].min-=W;        if(a[o].min<=0)del(o);//维护区间num        return;    }    pushdown(o);    int m=(a[o].l+a[o].r)>>1;    if(r<=m)change(ls,l,r);    else if(l>m)change(rs,l,r);    else    {        change(ls,l,m);        change(rs,m+1,r);    }    pushup(o);}void find(int o){    if(a[o].l==a[o].r)    {        ans[O]=a[o].l;        return;    }    pushdown(o);    if(a[ls].sum>=V)find(ls);    else    {        V-=a[ls].sum;//逻辑细节不要忘        find(rs);    }    pushup(o);}int main(){    while(~scanf("%d%d",&m,&n))    {        build(1,1,n);        for(int i=1;i<=m;i++)        {            scanf("%d%d",&b[i].w,&b[i].v);            b[i].o=i;        }        sort(b+1,b+m+1);        for(int i=1;i<=m;i++)        {            W=b[i].w-b[i-1].w;            if(W)change(1,1,n);            V=b[i].v;            O=b[i].o;            if(a[1].sum<V)ans[O]=0;            else find(1);        }        for(int i=1;i<=m;i++)printf("%d ",ans[i]);puts("");    }    return 0;}/*【trick&&吐槽】1,设计到大数据,都要考虑爆int。2,思维逻辑要清楚,找最早完成时间有减法不要忘记。【题意】有n(2e5)天,每天有一个可以工作的时间。有m(2e5)个询问,对于每个询问,是关于(准备时间A,完成时间B)的pair,()内的值都是1e6范围即,我们每天想要工作,要先支出一定的准备时间A。然后,这天的总时间,减去准备时间,剩下的时间作为我们的有效工作时间。如果有效工作时间(肯定有效工作时间要>0)之和>=完成时间B,那我们就完工啦。问最早的完工时间(如果无法完工,输出0)【类型】数据结构-线段树【分析】这题怎么做呢?我们发现,我们要求的是——∑(每天时间-准备时间),然而把<=0的筛掉,再求最早的>=完成时间的位置于是就发现,对于问题的处理,如果我们把准备时间排序,那问题处理起来就好一些了——因此,做法出来啦——1,我们建一棵线段树,用来存一定日期范围的可行工作时间2,对于每个询问,把准备时间作为关键字进行排序。3,对于每个询问,用后准备时间减去前准备时间,这个差值用在线段树上,来维护区间工作时间。4,然后直接从每个节点,向左走,向右走,处理询问找到最早工作时间就好啦。细节——线段树中要存哪些信息呢?1,基础的左右端点。2,做题首先就需要的——区间和sum3,配合区间减法使用的延迟标记这个时候,如果我们做区间减法,会怎样呢?区间和要怎么算?这里有两种做法——1,记录区间有效的num值,每次之间sum-=num*W2,从下区间合并得到。如果只考虑2,其实还是没法考虑减法对sum的影响。于是我们还是要记录区间的有效num,同时还要记录区间最小值来维护这个num然后对于区间减法——步骤1,sum-=num*W步骤2,检查合法性。如果区间最小值<=0,那么就向下删,然后答案从下层pushup得到。剩下的最后就是关于线段树的pushup()和pushdown()了。掌握几个原则就好了——1,flag只向下pushdown()2,每次修改一个区间后,我们的修改立即生效,flag只向下延展。修改包括:区间sum,延迟标记flag,区间最小值min,【时间复杂度&&优化】因为每个点最多只删除一次,所以时间复杂度为O((n+m)logn)*/


1 0
原创粉丝点击