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':' ');
		}
	}
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章