GTW likes gt
Accepts: 132
Time Limit: 2000/1000 MS (Java/Others)
Memory Limit: 131072/131072 K (Java/Others)
问题描述
从前,有nn只萌萌的GT,他们分成了两组在一起玩游戏。他们会排列成一排,第ii只GT会随机得到一个能力值b_ibi。在第ii秒的时候,第ii只GT可以消灭掉所有排在他前面的和他不是同一组的且能力值小于他的GT。 为了使游戏更加有趣,GT的首领GTW会发功mm次,第ii次发功的时间为c_ici,则在第c_ici秒结束后,b_1,b_2,...,b_{c_i}b1,b2,...,bci都会增加1。 现在,GTW想知道在第nn秒之后,会有几只GT存活下来。
输入描述
第一行只有一个整数T(T\leq 5)T(T≤5),表示测试数据组数。 第二行有两个整数n,mn,m。表示GT的个数和GTW发功的次数。(1\leq n \leq 50000,1\leq m\leq 500001≤n≤50000,1≤m≤50000) 第三到n+2n+2行,每行有两个整数a_i,b_iai,bi,表示第ii只GT在哪个组和他的能力值 (0\leq a[i]\leq 1,1\leq b[i]\leq 10^6)(0≤a[i]≤1,1≤b[i]≤106) 第n+3n+3行到第n+m+2n+m+2行,每行有一个整数c_ici,表示GTW第ii次发功的时间。1\leq c[i]\leq n1≤c[i]≤n
输出描述
总共TT行,第ii行表示第ii组数据中,GT存活的个数。
输入样例
1 4 3 0 3 1 2 0 3 1 1 1 3 4
输出样例
Hint
第11秒后 能力值为4\ 2\ 3\ 14 2 3 1 第22秒后 能力值为4\ 2\ 3\ 14 2 3 1 第33秒后 能力值为5\ 3\ 4\ 15 3 4 1,第22只GT被第33只GT消灭掉了 第44秒后 能力值为6\ 4\ 5\ 26 4 5 2 c_ici并不是有序的
思路:其实很简单,把前Ci个数字+1意味着把后面n-Ci个数字-1,只需要用一个datle数组记录到哪一个改偏移多少就好,现在就是解决如何快速删除前面比当前小的元素的问题,很简单,用优先队列就可以实现logn的操作,代码如下
1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<queue> 5 using namespace std; 6 int const maxn=50005; 7 int inibo[maxn],inival[maxn],sptr,datle[maxn]; 8 priority_queue< int,vector< int >,greater< int > > a,b; 9 int main() 10 { 11 int T; 12 scanf("%d",&T); 13 while(T--) 14 { 15 int n,m; 16 scanf("%d%d",&n,&m); 17 while(!a.empty()) 18 a.pop(); 19 while(!b.empty()) 20 b.pop(); 21 for(int i=1;i<=n;i++) 22 { 23 scanf("%d%d",&inibo[i],&inival[i]); 24 } 25 memset(datle,0,sizeof(datle)); 26 for(int i=1;i<=m;i++) 27 { 28 int temp; 29 scanf("%d",&temp); 30 datle[temp+1]++; 31 } 32 for(int i=1;i<=maxn-5;i++) 33 { 34 datle[i]+=datle[i-1]; 35 } 36 sptr=1; 37 for(int i=1;i<=n;i++) 38 { 39 int temp=inival[i]-datle[i]; 40 //printf("%d\n",temp); 41 int bo=inibo[i]; 42 if(bo) 43 { 44 while(!a.empty()&&a.top()<temp) 45 { 46 //printf("aaapop%d %d %d\n",i,temp,a.top()); 47 a.pop(); 48 } 49 b.push(temp); 50 } 51 else 52 { 53 while(!b.empty()&&b.top()<temp) 54 { 55 //printf("bbbpop%d %d %d\n",i,temp,b.top()); 56 b.pop(); 57 } 58 a.push(temp); 59 } 60 } 61 int ans=a.size()+b.size(); 62 printf("%d\n",ans); 63 } 64 return 0; 65 }
题目很简单,主要是想记录下优先队列的相关操作
#include<queue>
priority_queue< int,vector< int >,greater< int > > a,b;//小根堆
priority_queue<int> Q;//大根堆less
int a[5]={3,4,5,2,1};priority_queue<int> Q(a,a+5);//构造函数struct node{int priority;int value;friend bool operator < (node n1, node n2) //操作符重载(重载小于号得到大根堆){return n1.priority < n2.priority;}};priority_queue<node> qn;//自定义排序方式struct board
{
int h;
int x;
int y;
bool operator < (const board &p) const //直接重载
{
return this->h<p.h;
}
};priority_queue<board> q;empty() 如果优先队列为空,则返回真
pop() 删除第一个元素
push() 加入一个元素
size() 返回优先队列中拥有的元素的个数
top() 返回优先队列中有最高优先级的元素