zoukankan      html  css  js  c++  java
  • Codeforces 589G Hiring (NEERC 2015 G题)

    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 3
    4 2 5
    1 3
    2 5
    3 4
    
    output
    1 3 0 


    当时不会写 暴力超时

    想到线段树但是不会写

    终于在zb大爷的指导下过了这个题

    zb大爷是厉害啊!


    题意是有m个人 n天

    接下来n个数 表示每一天有一个时间

    接下来m行 两个数 d和r

    d表示每个人想工作之前必须每天都做准备的时间

    r表示需要工作的总时间

    问每个人最早在第几天结束工作


    如果某一天的t>一个人的d 那么这个人可在这一天工作t-d小时

    一个人需要工作的总时间是r

    如果按d和t排序

    从大往小了来 这样遇到每一天时,插入到线段树里

    遇到人时 查询区间和 区间和-d*区间里的天数>=r时表示可以在这一段区间里完成工作

    真巧妙啊


    *需要注意一点的是区间和可能爆int

    数据结构给人的感觉就是 我会写但是我不会用难过

    #include<bits/stdc++.h>
    using namespace std;
    const int lim = 2e5+10;
    int m,n;
    long long sum[lim<<2];
    int cnt[lim<<2];
    
    struct self
    {
        int d,r,k;
        int pos;
    }s[lim<<2];
    
    int cmp(self a,self b)
    {
        return a.d==b.d?a.k<b.k:a.d<b.d;
    }
    int ans[lim];
    void build(int o,int l,int r)
    {
        if(l==r)
        {
            sum[o]=cnt[o]=0;
            return;
        }
        int mid=(l+r)>>1;
        build(o<<1,l,mid);
        build(o<<1|1,mid+1,r);
    }
    
    void add(int o,int l,int r,int i)
    {
        if(l==r)
        {
            sum[o]+=(long long)s[i].d;
            cnt[o]++;
            return;
        }
        sum[o]+=(long long)s[i].d;
        cnt[o]++;
        int mid=(l+r)>>1;
        if(s[i].pos<=mid)
            add(o<<1,l,mid,i);
        else
            add(o<<1|1,mid+1,r,i);
    }
    
    int query(int o,int l,int r,int i,int has)
    {
        if(l==r)
            return l;
        int mid=(l+r)>>1;
        if(has+sum[o<<1]-cnt[o<<1]*s[i].d>=s[i].r)
            return query(o<<1,l,mid,i,has);
        else
            return query(o<<1|1,mid+1,r,i,has+sum[o<<1]-cnt[o<<1]*s[i].d);
    }
    
    int main()
    {
        scanf("%d%d",&n,&m);
        build(1,1,m);
        for(int i=1;i<=m;i++)
        {
            scanf("%d",&s[i].d);
            s[i].k=0;
            s[i].pos=i;
        }
        for(int i=m+1;i<=m+n;i++)
        {
            scanf("%d%d",&s[i].d,&s[i].r);
            s[i].k=1;
            s[i].pos=i-m;
        }
        sort(s+1,s+m+n+1,cmp);
        for(int i=m+n;i>=1;i--)
        {
            if(s[i].k==0)
                add(1,1,m,i);
            else
            {
                if(sum[1]-cnt[1]*s[i].d>=s[i].r)
                    ans[s[i].pos]=query(1,1,m,i,0);
            }
        }
        for(int i=1;i<=n;i++)
            printf("%d ",ans[i]);
        return 0;
    }



  • 相关阅读:
    01背包问题学习笔记
    状态压缩动态规划学习笔记
    并查集算法详解
    洛谷 P2939 [USACO09FEB]改造路Revamping Trails
    算法竞赛进阶指南 通信线路
    算法竞赛进阶指南 道路与航线
    NOIP2009 T3 最优贸易
    NOIP2017 Day1 T3 逛公园
    5.Go 语言数据类型:数组与切片
    4. Go 语言数据类型:byte、rune与字符串
  • 原文地址:https://www.cnblogs.com/abgnwl/p/6550336.html
Copyright © 2011-2022 走看看