题目链接:https://codeforces.com/problemset/problem/1185/C2
题目大意:给出一个包含n个元素的数组A,A[i]表示第i个人做完试卷需要多久。一场考试持续m分钟。问第i个人想要写完试卷,前i-1个人最少多少个需要放弃考试。
思路:其实我过的还是比较迷的。。因为没什么好方法就想着暴力试试。。就过了。。200ms+。。好了,下面思路(可能不是很好
由于A[i]是乱序的,并且每个A[i]只用关心前i-1个人就好了。所以我们维护一个符合条件的花费时间的优先队列Que。每当读入一个人时,如果能够直接加上,那就直接加上,A[i]放入Que中。否则需要使前面某些人出来。
让那些人出来呢?我们贪心的让花费时间最多的人出来。分为两种情况:
1:如果A[i]<Que.top()。说明这个人比之前某一个人花费的时间要少,就把这个人放进去,前面那个人放弃,还能空出更多的时间。
2:如果A[i]>=Que.top()。说明这个人很浪费时间,先将他符合要求的情况求出,输出答案之后,立刻将他踢出去。
刷新答案即可。
Update:
后来突然想到了一个更简单的方法。我们记录一下时间A[i]的出现次数。每次查看的时候,从高到低枚举一下就好了。时间复杂度O(100*n)。比我那个可能会T的思路好多了QWQ。
ACCode1:
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<time.h>
#include<math.h>
// srand((unsigned)time(NULL));rand();
#include<map>//unordered_map
#include<set>//multiset
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
#define ll long long
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define clean(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=2e5+10;
//const int MAXM=10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll MOD=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
//unsigned register
// ios::sync_with_stdio(false)
int A[MAXN];
int Stk[MAXN],top;
int n,m;
int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=1;i<=n;++i) scanf("%d",&A[i]);
priority_queue<int> que;
int sum=0,cnt=0;
for(int i=1;i<=n;++i){
int tmp=sum+A[i];
// printf("tmp=%d\n",tmp);
if(tmp<=m){
que.push(A[i]);sum=tmp;
printf("%d%c",cnt,i==n?'\n':' ');continue ;
}
top=0;
if(A[i]>que.top()){//该元素是最大的
while(tmp>m&&que.size()){//取出直到符合要求
int u=que.top();que.pop();cnt++;
Stk[++top]=u;//将取出的放到临时数组中
tmp-=u;//更新值
}
printf("%d%c",cnt,i==n?'\n':' ');
tmp-=A[i];++cnt;//将该值取出
for(int j=1;j<=top;++j){//把之前取出的都放进去
que.push(Stk[j]);--cnt;
tmp+=Stk[j];
}
sum=tmp;
continue ;
}
//该元素不是最大的,将最大的换成该元素
int u=que.top();que.pop();cnt++;//取出一个最大的
tmp-=u;
que.push(A[i]);//放入次大的
printf("%d%c",cnt,i==n?'\n':' ');
sum=tmp;
}
}
}
Update ACCode2:
#include<stdlib.h>
#include<string.h>
#include<stdio.h>
#include<time.h>
#include<math.h>
// srand((unsigned)time(NULL));rand();
#include<map>//unordered_map
#include<set>//multiset
#include<deque>
#include<queue>
#include<stack>
#include<bitset>
#include<string>
#include<fstream>
#include<iostream>
#include<algorithm>
#define ll long long
#define PII pair<int,int>
#define PLL pair<ll,ll>
#define clean(a,b) memset(a,b,sizeof(a))
using namespace std;
const int MAXN=2e5+10;
//const int MAXM=10;
const int INF32=0x3f3f3f3f;
const ll INF64=0x3f3f3f3f3f3f3f3f;
const ll MOD=1e9+7;
const double PI=acos(-1.0);
const double EPS=1.0e-8;
//unsigned register
// ios::sync_with_stdio(false)
int Cnt[110],A[MAXN];
int n,m;
int main(){
while(~scanf("%d%d",&n,&m)){
for(int i=0;i<=100;++i) Cnt[i]=0;
for(int i=1;i<=n;++i) scanf("%d",&A[i]);
int sum=0;
for(int i=1;i<=n;++i){
int tmp=sum+A[i],cnt=0;
if(tmp<=m){
Cnt[A[i]]++;sum+=A[i];
printf("%d%c",cnt,i==n?'\n':' ');continue ;
}
for(int j=100;j>=1;--j){
int siz=Cnt[j],k=ceil(1.0*(tmp-m)/j);
if(k<=siz){//足够踢出k个人
cnt+=k;tmp-=k*j;
break;
}
cnt+=siz;tmp-=siz*j;
}Cnt[A[i]]++;sum+=A[i];
printf("%d%c",cnt,i==n?'\n':' ');
}
}
}