標籤:api 編號 targe 範圍 img 管理 row oid body
2830 蓬萊山輝夜 http://codevs.cn/problem/2830/題目描述 Description
在幻想鄉中,蓬萊山輝夜是月球公主,居住在永遠亭上,二次設定說她成天宅在家裡玩電腦,亦稱NEET姬
一天,她要她幫忙升級月球的網路伺服器,應為註冊使用者過多(月兔和地球上的巫女都註冊了……),所以作為代理管理員(俗稱網管)的她,非常蛋疼。
註冊使用者格式:
TouhouMaiden 2004 200
其中前面的Touhoumaiden是預設,不做更改,第一個數是標識,第二個數是每次接受資訊訪問的間隔用時。
你要做的事,就是給定一群使用者及n,求出這n次資訊訪問中,訪問到了誰?
presented by Izayoi sakuya
輸入描述 Input Description
以題目預設格式輸入,另起一行以‘#’結束,在其一行輸入n
輸出描述 Output Description
n行,每行輸出第行次後,資訊訪問到了誰?若在一個時間有若干少女被訪問到,輸出字典序最小的那位少女的標識
範例輸入 Sample Input
TouhouMaiden 2004 200
TouhouMaiden 2005 300
#
5
範例輸出 Sample Output
20042005200420042005
資料範圍及提示 Data Size & Hint
標識和每次資訊訪問間隔均在integer內,n<=10000
原本是要用到堆,但深搜+時間即可搞定
資料有點少但也都夠變態了
本題描述有問題。題目中說:“若在一個時間有若干少女被訪問到,輸出字典序最小的那位少女的標識”,然而範例是按字典序全部輸出
本題的意思:許多人排隊等待被訪問,他們每人都有一個編號(輸入資料每一行的第一個數字),和一個時間,時間為等待時間(輸入資料每一行的第二個數字)+已花費時間。他們排隊的順序為先按等待時間排序,若等待時間相同再按編號的字典序排序。然而每個人都想多次被訪問,所以他們每次被訪問完後,都會再去插隊,再等待他們相應的等待時間再次被訪問,訪問完了之後再去插隊……他們並不是老老實實的去排隊,而是插隊,插到等待時間+已花費時間比他還要長的人的前面。(也就是總時間少的人先被訪問)
所以可以建立一個小根堆,每次取出堆中的第一個元素,輸出編號,加上等待時間再放進堆裡去,迴圈n次。
#include<iostream>#include<cstdio>#include<algorithm>struct node{ int a,b,c;//a編號,b已花費時間,c等待時間 }e[10001];using namespace std;int n,s,i,l[10010];//s堆heap中元素的個數,l用於存放時間相同的少女的編號 char c[1001];node heap[10010];//堆 bool cmp(node k,node p){ return k.b<p.b;}void insert(node k)//向堆中加入元素 { s++; heap[s]=k; int p=s; while(p>1&&k.b<heap[p/2].b) { heap[p]=heap[p/2]; p/=2; } heap[p]=k;}void heapify(int k)//維護小根堆 { int left=k*2,right=k*2+1; int minn=k; if(left<=s) minn=heap[minn].b<heap[left].b ? minn:left; if(right<=s) minn=heap[minn].b<heap[right].b ? minn:right; if(minn!=k) { swap(heap[minn],heap[k]); heapify(minn); }}node get()//取出堆中第一個元素 { node k=heap[1]; heap[1]=heap[s]; s--; heapify(1); return k;}int main(){ cin>>c; while(c[0]!=‘#‘) { i++; scanf("%d%d",&e[i].a,&e[i].b); e[i].c=e[i].b; insert(e[i]); cin>>c; } scanf("%d",&n); while(n) { bool ok=false; node h=get();//取出堆中的第一個元素 int o=h.a;//這次要輸出的元素的編號 int su=0;//相同時間的少女的個數 while(h.b==heap[1].b) //有少女在相同時間被訪問到 { ok=true; l[++su]=h.a;//存進去 h.b+=h.c;//加上等待時間 insert(h);//再放回堆裡 h=get();//再取出堆得第一個元素 o=min(o,h.a); } l[++su]=h.a; h.b+=h.c; insert(h);//如過存在幾個少女同一時間被訪問到的情況,那根據上面的while,最後一個同一時間的少女沒有取出來放入l數組,所以要加進去 //如果不存在幾個少女同一時間被訪問的情況,語句l[++su]=h.a執行沒有影響,實際有作用的是後兩句 if(ok) { sort(l+1,l+su+1);//按字典序輸出 for(int i=1;i<=su;i++) printf("%d\n",l[i]); n-=su; continue; } printf("%d\n",o);//沒有少女在同一時間被訪問,直接輸出編號 n--; }}
codevs 2830 蓬萊山輝夜