单调队列[SCOI2009]生日礼物
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了单调队列[SCOI2009]生日礼物相关的知识,希望对你有一定的参考价值。
题目描述
小西有一条很长的彩带,彩带上挂着各式各样的彩珠。已知彩珠有N个,分为K种。简单的说,可以将彩带考虑为x轴,每一个彩珠有一个对应的坐标(即位置)。某些坐标上可以没有彩珠,但多个彩珠也可以出现在同一个位置上。
小布生日快到了,于是小西打算剪一段彩带送给小布。为了让礼物彩带足够漂亮,小西希望这一段彩带中能包含所有种类的彩珠。同时,为了方便,小西希望这段彩带尽可能短,你能帮助小西计算这个最短的长度么?彩带的长度即为彩带开始位置到结束位置的位置差。
输入输出格式
输入格式:
第一行包含两个整数N, K,分别表示彩珠的总数以及种类数。接下来K行,每行第一个数为Ti,表示第i种彩珠的数目。接下来按升序给出Ti个非负整数,为这Ti个彩珠分别出现的位置。
输出格式:
输出应包含一行,为最短彩带长度。
1 #include <cstdio> 2 #include <vector> 3 #include <queue> 4 using namespace std; 5 #define INT_MAX 2147483647 6 int n,k,t[60],x,ans=INT_MAX; 7 vector<int> p[60]; 8 struct ball{ 9 int num,clr; 10 bool operator < (const ball &a) const { 11 return p[clr][num]>p[a.clr][a.num]; 12 } 13 }; 14 priority_queue<ball> que; 15 int main() 16 { 17 scanf("%d%d",&n,&k); 18 for (int i=0;i<k;i++) 19 { 20 scanf("%d",&t[i]); 21 for (int j=0;j<t[i];j++) 22 { 23 scanf("%d",&x); 24 p[i].push_back(x); 25 } 26 } 27 int l=INT_MAX,r=0; 28 for (int i=0;i<k;i++) 29 { 30 ball tball; 31 tball.num=0; 32 tball.clr=i; 33 int tballpos=p[tball.clr][tball.num]; 34 if (tballpos<l) l=tballpos; 35 if (tballpos>r) r=tballpos; 36 que.push(tball); 37 } 38 ans=r-l; 39 for (int i=0;i<n-k;i++) 40 { 41 ball pball,tball; 42 pball=que.top(); 43 que.pop(); 44 if (pball.num==t[pball.clr]-1) break; 45 46 tball.num=pball.num+1; 47 tball.clr=pball.clr; 48 int tballpos=p[tball.clr][tball.num]; 49 que.push(tball); 50 51 pball=que.top(); 52 int pballpos=p[pball.clr][pball.num]; 53 54 l=pballpos; 55 if (tballpos<l) l=tballpos; 56 if (tballpos>r) r=tballpos; 57 if (r-l<ans) ans=r-l; 58 } 59 printf("%d\n",ans); 60 }
以上是关于单调队列[SCOI2009]生日礼物的主要内容,如果未能解决你的问题,请参考以下文章