zoukankan      html  css  js  c++  java
  • 2020.12.1考试题解

    L君找工作

    【问题描述】

    L君是个热爱生活的好青年,暑假来临,他要为自己找份工作。
    暑假共有 M 天,从1到m进行编号,在第 i 天,L君共有 ti 的时间供自己自工作,
    当然,每一天L君可以选择休息不去工作。
    通过好朋友P君的帮助,现在L君收集到了N份工作信息,工作从 1 到 N 编号,
    根据收集来的信息,L君给每份工作确定了两个参数dj 和 rj;
    若某天L君决定参与第 j 份工作,那么不论哪一天,他都会先花 dj 的时间准
    备这一天的工作。
    若L君要参与第 j 份工作,那么他一共要工作 的时间才能算完成这项工作。
    因此,若L君在第 i 天选择参与第 j 份工作,那么他会先花dj的时间来准备,
    这天剩下能用来工作的时间他就会去做这份工作,若 ti < dj 则说明这天不能参与这
    份工作。
    一份工作需要做至少 的时间才算完成(一天准备工作的时间不算在内),
    因此一份工作可能需要多天才能完成。
    L君精力有限,因此他只想在暑假选择单独一份工作参与,又由于L君想尽
    早结束工作去找好友P君一起玩耍,所以他想请你求出在单独只做一份工作的情
    况下每份工作最早能在第几天完成。你能帮助他吗?
    

    【输入格式】

    第一行包含两个正整数 n, m 表示工作数与天数。
    第二行包含m个正整数 ti,表示每天的工作时间。
    接下来n行每行包含两个非负整数 di, ri,表示这份工作每天需要的准备时间
    与需要完成的工作总时间。
    

    【输出格式】

    按输入的顺序输出一行 n 个整数,表示每份工作最早在第几天可以做完。若
    这份工作在这 m 天内无法完成则输出0.
    

    【样例输入】

    3 3
    4 2 5
    1 3
    2 5
    3 4
    

    【样例输出】

    1 3 0
    

    分析:

    暴力做法,直接(;O(n imes m);)扫描,可以拿(;25;)分。

    可能还有其他奇奇怪怪的优化可以拿部分分,但我不会这里就不讲了。

    正解:

    我们对于每一个任务,要求满足(;sumlimits_{j=1}^m{(t_j-d_i)}>r_i;)的最小的(;j;)

    可以发现,这是一个二维偏序,这里有两种做法。

    (<1>;)我们可以用主席树,建立一个以输入顺序为序的主席树,对于每一个任务,我们可以二分区间查找前缀和,找出答案。

    (<2>;)我们考虑去掉一维,采用离线。

    我们将天数按时间从大到小排序,任务也按准备时间从大到小排序,这样一来,我们每次将大于当前任务的(;d_i;)的天加入序列。很容易得知,我们每天都只会入列一次,减少了很多重复的扫描,且之前的可以被后面的继承。

    (Code):

    #include<bits/stdc++.h>
    using namespace std;
    const int N=2e5+7,M=2e5+7;
    #define il inline
    #define vocaloid(v) (v>='0'&&v<='9')
    template <typename T>
    il void read(T &x)
    {
    	x=0;char v=getchar();
    	while(!vocaloid(v)) v=getchar();
    	while(vocaloid(v)) {x=(x<<1)+(x<<3)+v-'0';v=getchar();}
    }
    template <typename T>
    il void write(T x) {if(x>9) write(x/10); putchar(x%10+'0');}
    template <typename T>
    il void print(T x) {write(x); putchar('
    ');}
    il int Max(int x,int y) {return x>=y?x:y;}
    struct mission{
    	int r,co,pos;
    }Te[N];
    struct Day{
    	int t,pos;
    }d[M];
    int n,m,ans[N];
    int c1[M],c2[M],t[M];
    il bool cmp1(Day x,Day y) {return x.t==y.t?x.pos<y.pos:x.t>y.t;}
    il bool cmp2(mission x,mission y) {return x.r==y.r?x.co<y.co:x.r>y.r;}
    il int lowbit(int x) {return x&(-x);} 
    il void change(int *c,int x,int val)
    {
    	for(int i=x;i<=m;i+=lowbit(i))
    		c[i]+=val;
    }
    il int ask(int *c,int x)
    {
    	int ans=0;
    	for(int i=x;i;i-=lowbit(i))
    		ans+=c[i];
    	return ans;
    }
    int main()
    {
    	freopen("work.in","r",stdin);
    	freopen("work.out","w",stdout);
    	read(n),read(m);
    	for(int i=1;i<=m;i++)
    	{
    		read(t[i]);
    		d[i]=(Day){t[i],i};
    	}
    	for(int i=1;i<=n;i++)
    	{
    		read(Te[i].r),read(Te[i].co);
    		Te[i].pos=i;
    	}
    	sort(d+1,d+1+m,cmp1);
    	sort(Te+1,Te+1+n,cmp2);
    	int IA=1;
    	for(int i=1;i<=n;i++)
    	{
    		for(;IA<=m&&d[IA].t>=Te[i].r;++IA)
    			change(c1,d[IA].pos,d[IA].t),
    			change(c2,d[IA].pos,1);
    		int sum=ask(c1,m)-ask(c2,m)*Te[i].r;
    		if(sum<Te[i].co) {ans[Te[i].pos]=0; continue ;}
    		int l=1,r=m,mid;
    		while(l<=r)
    		{
    			mid=(l+r)>>1;
    			sum=ask(c1,mid)-ask(c2,mid)*Te[i].r;
    			if(sum>=Te[i].co) r=mid-1;
    			else l=mid+1;
    		}
    		ans[Te[i].pos]=l;
    	}
    	for(int i=1;i<=n;i++)
    		write(ans[i]),putchar(' ');
    	return 0;
    }
    
  • 相关阅读:
    场景调研
    12.8
    12.7
    12.6
    12.5
    12.4
    12.3
    重启oracle数据库的操作方法
    oracle创建dblink方法
    SQL*Loader 详解
  • 原文地址:https://www.cnblogs.com/MIKU5201314/p/14086763.html
Copyright © 2011-2022 走看看