1306: Manor
Time Limit: 1 Sec Memory Limit: 128 MB
Submit: 150 Solved: 48
[Submit][Status][Web Board]
Description
Bob有n个正整数,他将这n个整数根据大小划分成两部分。对于小于等于k的整数放在集合A中,其余的放在集合B中。每次他从集合B中取出一个最大的值,将其变成0放入A集合中。然后将A集合中所有的元素都增加a,如果此时A中元素大于k,那么要将该元素放入B中,同时将B集合中剩余的元素都增加b。Bob现在想知道经过m次操作后,B集合中元素的个数。
Input
有多组测试数据。
每组测试数据的第一行为4个整数n,k,a,b,n<=100000,k<=10^3,a,b<=100, 含义同上。接下的来的一行有n个数,表示这n个数的初始值(初始值小于等于200)。接下来的一行有一个整数q(q<=100),表示有q个询问。接下来有q行,每行一个正整数m(m<=200),表示第m次操作。
Output
对于每一个询问m,输出第m次操作前集合B中元素的个数。
Sample Input
5 100 40 20
1000 250 300 10 25
10
1
2
3
4
5
6
7
8
9
10
4 100 10 10
105 150 25 75
4
1
2
3
4
Sample Output
3
2
2
3
3
3
3
3
3
3
2
1
0
1
参照了某牛解法:http://blog.csdn.net/libin56842/article/details/10769305
ORZ、、、、
优先队列维护一下就行了,B里面的数没用,只需要维护A里面的数就行了
每次弹出最大的数(最初值+i*a)
AC代码:
#include<iostream>
#include<cmath>
#include<queue>
#include<cstdio>
#include<algorithm>
using namespace std;
struct node
{
int x,time;
bool operator <(const node &a)const
{
if(a.time!=time) return a.time<time;
return a.x>x;
}
}pre;
priority_queue<node>Q;
int main()
{
int n,k,a,b;
while(scanf("%d%d%d%d",&n,&k,&a,&b)!=EOF)
{
int i,ans[205],len=0,x;
while(!Q.empty())Q.pop();
for(i=0;i<n;i++)
{
scanf("%d",&x);
if(x<=k){
pre.x=x;
pre.time=0;
Q.push(pre);
}
else len++;
}
for(i=1;i<201;i++)
{
ans[i]=len;
if(len)
{
pre.time=i-1;
pre.x=0;
Q.push(pre);
len--;
}
while(!Q.empty())
{
pre=Q.top();
if(pre.x+(i-pre.time)*a<=k)break;
Q.pop();
len++;
}
}
int q,m;
scanf("%d",&q);
while(q--)
{
scanf("%d",&m);
printf("%d\n",ans[m]);
}
}
return 0;
}