CF-1185C2-Exam in BerSU (hard version) (思维+贪心暴力)

题目链接: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':' ');
		}
	}
}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值