码迷,mamicode.com
首页 > 其他好文 > 详细

HDU 5596

时间:2015-12-15 20:59:37      阅读:133      评论:0      收藏:0      [点我收藏+]

标签:

题目:

http://acm.hdu.edu.cn/showproblem.php?pid=5596

这道题可以很巧妙的用O(n)的时间复杂度做出来的。首先,当我们用一个数组c存储gt发功的时间时,以该时间为下标之前的b值都会加1,所以可以用c[i] += c[i-1],以获得当前节点之前,已累计法功多少次了,然后c[y]-c[x](y>x)就是以x为下标的gt,到y时间时,通过发功增加的量。

至于为什么要倒着处理呢,因为我们是要去掉小的元素,这样,我们只要从后往前,保存最大的元素,只要存在小于最大元素的,该元素就可以去掉了。

还有,max0、max1分别是1组的最大值和0组的最大值,以gt[i].b-c[i-1]-max0这个式子为例,我们这里假设x<y,max0 = gt[y].b-c[y-1],所以前面那个式子就可以化成gt[x].b-c[x-1]-gt[y].b-c[y-1] = gt[x].b-gt[y].b+c[y-1]-c[x-1],由我们前面的推导,c[y-1]-c[x-1]就是gt[x].b增加的量,这个值加上gt[x].b,如果减去gt[y].b小于0的话,说明该gt是要去掉的,同时要更新max1的值,以为此时处理的是0组的情况,保存最大的。

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<algorithm>
 4 #define maxn 50005
 5 #define inf 0x3f3f3f3f
 6 using namespace std;
 7 struct node{
 8     int group;
 9     int b;
10 };
11 node gt[maxn];
12 int c[maxn];
13 int main(){
14     int t;
15     scanf("%d",&t);
16     while(t--){
17         int n,m;
18         memset(c,0,sizeof(c));
19         scanf("%d%d",&n,&m);
20         for(int i = 1;i<=n;i++){
21             scanf("%d%d",&gt[i].group,&gt[i].b);
22         }
23         for(int i = 1;i<=m;i++){
24             int temp;
25             scanf("%d",&temp);
26             c[temp]++;
27         }
28         for(int i = 1;i<=n;i++){
29             c[i] += c[i-1];
30         } 
31         int ans = n;
32         int max0 = -inf,max1 = -inf;
33         for(int i = n;i>0;i--){
34             if(gt[i].group){
35                 if(gt[i].b-c[i-1]-max0<0)
36                     ans--;
37                 max1 = max(max1,gt[i].b-c[i-1]);
38             }else{
39                 if(gt[i].b-c[i-1]-max1<0)
40                     ans--;
41                 max0 = max(max0,gt[i].b-c[i-1]);
42             }
43         }
44         printf("%d\n",ans);
45     } 
46     return 0;
47 }

 

HDU 5596

标签:

原文地址:http://www.cnblogs.com/zqy123/p/5049442.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!