題目鏈接: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':' ');
}
}
}