处理器(Processor,Seoul 2008,LA 4254)

9 篇文章 0 订阅

AC通道:
https://icpcarchive.ecs.baylor.edu/index.php?option=com_onlinejudge&Itemid=8&page=show_problem&problem=2255


处理器


Description

n 个任务,每个任务有 3 个参数 ridi wi ,表示必须在时刻 [ri,di] 之内执行,工作量为 wi
处理器执行的速度可以变化,当执行速度为 s 时,一个工作量为 wi 的任务需要执行 wi/s 个单位时间。
另外,任务不一定要连续执行,可以分成若干块。
你的任务时求出处理器在执行过程中最大速度的最小值。
处理器速度可以是任意整数值。

假设有 5 个任务,ri di 分别是 [1,4] [3,6] [4,5] [4,7] [5,8] ,工作量分别为 2,3,2,2,1 ,则下图是一个最优执行方案,最大速度为 2

这里写图片描述


Input

输入的第一行为数据组数 T T20 )。
每组数据的第一行为整数 n 1n10000);
以下 n 行每行包含 3 个整数 ri,di,wi 1ri<di2000 1wi1000 )。


Output

对于每组数据,输出在执行过程中处理器最大速度的最小值。


Sample Input

3
5
1 4 2
3 6 3
4 5 2
4 7 2
5 8 1
6
1 7 25
4 8 10
7 10 5
8 11 5
10 13 10
11 13 5
8
15 18 10
20 24 16
8 15 33
11 14 14
1 6 16
16 19 12
3 5 12
22 25 10


Sample Output

2
5
7


Solution

首先,这个题目有点坑的是,当你判断时间为 x ,第 i 个任务能不能执行时,需要满足的条件是: rix && di>x ,因为这个任务并不是在这个时间点执行,而是在这个时间点与下一个时间点之间执行。

二分答案。

首先按 ri 排序。

枚举每个时间点,对于这个时间点上的任务,我们按照 di 从小到大进行执行。
这就需要用到优先队列。

还有一个优化:当优先队列为空时,可以直接跳到下一个任务的开始时间。


Code

[cpp]
  1. #include <iostream>  
  2. #include <cstdio>  
  3. #include <algorithm>  
  4. #include <queue>  
  5.   
  6. using namespace std;  
  7.   
  8. const int MAXN=10000;  
  9.   
  10. struct Pro{  
  11.     int l,r,w;  
  12.     bool operator > (const Pro&b)const{  
  13.         return r>b.r;  
  14.     }  
  15. }s[MAXN+10];  
  16.   
  17. priority_queue<int,vector<Pro>,greater<Pro> > q;  
  18.   
  19. inline int Max(int x,int y){  
  20.     return x>y?x:y;  
  21. }  
  22.   
  23. bool cmp(Pro x,Pro y){  
  24.     return (x.l<y.l);  
  25. }  
  26.   
  27. inline int in(){  
  28.     int ans=0;  
  29.     char x=getchar();  
  30.     while(x<‘0’||x>‘9’)x=getchar();  
  31.     while(x>=‘0’&&x<=‘9’){ans=ans*10+x-‘0’;x=getchar();}  
  32.     return ans;   
  33. }  
  34.   
  35. int T,n;  
  36. int maxn;  
  37.   
  38. bool pan(int speed){  
  39.     while(!q.empty())q.pop();  
  40.     int now=1;  
  41.     for(int i=1;i<=maxn;i++){  
  42.         if(q.empty()){  
  43.             if(now>n)return true;  
  44.             i=s[now].l;  
  45.         }  
  46.         while(now<=n&&s[now].l<=i)q.push(s[now++]);  
  47.         int tmp=speed;  
  48.         while(tmp>0&&!q.empty()){  
  49.             Pro t=q.top();  
  50.             q.pop();  
  51.             if(t.r<=i)return false;  
  52.             if(t.w>tmp){  
  53.                 t.w-=tmp;  
  54.                 tmp=0;  
  55.                 q.push(t);   
  56.             }  
  57.             else  
  58.                 tmp-=t.w;  
  59.         }  
  60.     }  
  61.     return false;  
  62. }  
  63.   
  64. int main(){  
  65.     T=in();  
  66.     while(T–){  
  67.         maxn=0;  
  68.         n=in();  
  69.         for(int i=1;i<=n;i++){  
  70.             s[i].l=in();s[i].r=in();s[i].w=in();  
  71.             maxn=Max(maxn,s[i].r);  
  72.         }  
  73.         sort(s+1,s+n+1,cmp);  
  74.         int l=1,r=maxn,ans=maxn;  
  75.         while(l<=r){  
  76.             int mid=(l+r)/2;  
  77.             bool flag=pan(mid);  
  78.             if(flag){  
  79.                 if(ans>mid)ans=mid;  
  80.                 if(r!=mid-1)r=mid-1;  
  81.                 else break;  
  82.             }  
  83.             else{  
  84.                 if(l!=mid+1)l=mid+1;  
  85.                 else break;   
  86.             }  
  87.         }  
  88.         printf(”%d\n”,ans);  
  89.     }  
  90.     return 0;  
  91. }  
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值