更新:
这是中文题目的链接:
http://bestcoder.hdu.edu.cn/contests/contest_chineseproblem.php?cid=659&pid=1001
这道题还可以用优先队列来做,优先队列的特性可以很好的返回两个队列中b最小的值。
下面说过了,c[i] += c[i-1]是来获得前缀和。前面的节点没发功增加一次,就相当于b[i]-1,b[i]-c[i-1]的值,就是到达第i时间是,b[i]相对的减少量。我们设置两个队列,根据需要,将b[i]-c[i-1]的值分别放入不同的队列中,例如,当取到0组的数时,将该b[i]-c[i-1]放入0组队列,同时和1组队列的最小值比较,若1组较小,则去掉该元素,直到存在大的为止。
1 #include<stdio.h> 2 #include<queue> 3 #include<string.h> 4 #define maxn 50005 5 using namespace std; 6 struct node1{ 7 int num; 8 friend bool operator<(node1 a,node1 b){ 9 return b.num < a.num; 10 } 11 }; 12 struct node2{ 13 int group; 14 int b; 15 }; 16 node2 a[maxn]; 17 int c[maxn]; 18 int main(){ 19 int t; 20 scanf("%d",&t); 21 while(t--){ 22 int n,m; 23 memset(c,0,sizeof(c)); 24 priority_queue<node1>q[2]; 25 scanf("%d%d",&n,&m); 26 for(int i = 1;i<=n;i++){ 27 scanf("%d%d",&a[i].group,&a[i].b); 28 } 29 for(int i = 0;i<m;i++){ 30 int time; 31 scanf("%d",&time); 32 c[time]++; 33 } 34 int ans = n; 35 node1 cur; 36 for(int i = 1;i<=n;i++){ 37 c[i] += c[i-1]; 38 if(a[i].group){ 39 cur.num = a[i].b-c[i-1]; 40 q[1].push(cur); 41 while(!q[0].empty()&&q[0].top().num<cur.num){ 42 q[0].pop(); 43 ans--; 44 } 45 }else{ 46 cur.num = a[i].b-c[i-1]; 47 q[0].push(cur); 48 while(!q[1].empty()&&q[1].top().num<cur.num){ 49 q[1].pop(); 50 ans--; 51 } 52 } 53 } 54 printf("%d\n",ans); 55 } 56 return 0; 57 }
——————————————————我是分割线————————————————————————————————
题目:
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",>[i].group,>[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 }
---恢复内容结束---
题目:
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",>[i].group,>[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 }