1. 程式人生 > 其它 >CSP-J2020 洛谷P7072 直播獲獎(Splay/桶排序)

CSP-J2020 洛谷P7072 直播獲獎(Splay/桶排序)

題目描述

NOI2130 即將舉行。為了增加觀賞性,CCF 決定逐一評出每個選手的成績,並直播即時的獲獎分數線。本次競賽的獲獎率為 w%,即當前排名前 w% 的選手的最低成績就是即時的分數線。

更具體地,若當前已評出了 p 個選手的成績,則當前計劃獲獎人數為max(1,pw%)。如有選手成績相同,則所有成績並列的選手都能獲獎,因此實際獲獎人數可能比計劃中多。

作為評測組的技術人員,請你幫 CCF 寫一個直播程式。

輸入格式

第一行有兩個整數 n,w。分別代表選手總數與獲獎率。
第二行有 n 個整數,依次代表逐一評出的選手成績。

輸出格式

只有一行,包含 n 個非負整數,依次代表選手成績逐一評出後,即時的獲獎分數線。相鄰兩個整數間用一個空格分隔。

 

看到這道題,第一反應是用Splay,因為這道題支援兩個操作:插入元素和查詢第k大元素,套模板就行了。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 const int N=1e5+5;
 4 int n,w;
 5 int fa[N],lc[N],rc[N],vi[N],sze[N];
 6 int rt,T;
 7 bool Wrt(int x){
 8     return rc[fa[x]]==x;
 9 }
10 
11 void pushup(int x){//更新子樹大小 
12     sze[x]=sze[lc[x]]+sze[rc[x]]+1
; 13 } 14 15 void rot(int x){ 16 int y=fa[x],z=fa[y]; 17 int b=(lc[y]==x)?rc[x]:lc[x]; 18 fa[x]=z,fa[y]=x; 19 if(b) fa[b]=y; 20 if(z) (y==lc[z]?lc[z]:rc[z])=x; 21 if(x==lc[y]) rc[x]=y,lc[y]=b; 22 else lc[x]=y,rc[y]=b; 23 pushup(y);pushup(x); 24 } 25 26 void Splay(int
x,int tar){ 27 while(fa[x]!=tar){ 28 if(fa[fa[x]]!=tar) 29 Wrt(x)==Wrt(fa[x])?rot(fa[x]):rot(x); 30 rot(x); 31 } 32 if(!tar) rt=x; 33 } 34 35 void ins(int v){//插入元素 36 int x=rt,y=0,dir; 37 while(x){ 38 ++sze[y=x]; 39 if(v<=vi[x]) dir=0,x=lc[x]; 40 else dir=1,x=rc[x]; 41 } 42 fa[x=++T]=y,vi[x]=v,sze[x]=1; 43 if(y) (dir==0?lc[y]:rc[y])=x; 44 Splay(x,0); 45 } 46 47 int query(int x,int k){//查詢第k個數 48 while(1){ 49 int s=lc[x]?sze[lc[x]]+1:1; 50 if(k==s) return vi[x]; 51 if(k>s) k-=s,x=rc[x]; 52 else x=lc[x]; 53 } 54 } 55 56 int main(){ 57 scanf("%d%d",&n,&w); 58 for(int i=1;i<=n;i++){ 59 int x; 60 scanf("%d",&x); 61 int k=max(1,i*w/100); 62 ins(x); 63 cout<<query(rt,i-k+1)<<" "; 64 } 65 return 0; 66 }

當然,本題還有更簡單的方法,程式碼量也更小。

就是用桶排序,因為分數的範圍非常小,只有600;(桶的下標就是元素的值)

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+5;
int t[N],n,w;

int main(){
    scanf("%d%d",&n,&w);
    for(int i=1;i<=n;i++){
        int x,sum=0;
        scanf("%d",&x);t[x]++;
        for(int j=600;j>=0;j--){
            sum+=t[j];
            if(sum>=max(1,i*w/100)){
                cout<<j<<" ";
                break;
            }
        }
    }
    return 0;
} 

之前好像沒太多接觸過桶,今天又學到了,像這種題目值域比較小的,可以考慮用桶。