bzoj1293: [SCOI2009]生日礼物(stl堆)
1293: [SCOI2009]生日礼物
题目:传送门
题解:
据说这道题乱搞随便就水过了
本蒟蒻想到了一个用堆的水法(还专门学了学queue):
如果把每一种颜色的下一个位置都记录一下的话,一开始就把所有的颜色开头位置加入堆中,求一下ans
然后将最左边的颜色删掉换成下一个位置并加入堆然后更新答案
因为题目保证位置升序,所以如果问当前颜色的没有了下一个位置,那就退出
代码(有点丑,因为不会求堆底所以开了两个堆):
1 #include<cstdio> 2 #include<cstring> 3 #include<cstdlib> 4 #include<cmath> 5 #include<algorithm> 6 #include<queue> 7 using namespace std; 8 typedef long long LL; 9 10 int n,k; 11 struct node 12 { 13 LL x;int next; 14 node(){next=-1;} 15 friend bool operator <(node n1,node n2) 16 { 17 return n1.x>n2.x; 18 } 19 }a[1100000]; 20 struct node1 21 { 22 LL x; 23 friend bool operator <(node1 n1,node1 n2) 24 { 25 return n1.x<n2.x; 26 } 27 }b[1100000]; 28 priority_queue<node> q; 29 priority_queue<node1> v; 30 void clean(){while(q.empty()!=true)q.pop();} 31 int t[65]; 32 int main() 33 { 34 clean();int id=0; 35 scanf("%d%d",&n,&k);LL x; 36 for(int i=1;i<=k;i++) 37 { 38 scanf("%d",&t[i]); 39 for(int j=1;j<=t[i];j++) 40 { 41 scanf("%lld",&x); 42 a[++id].x=x;if(j!=t[i])a[id].next=id+1; 43 b[id].x=x; 44 } 45 } 46 int w=1; 47 for(int i=1;i<=k;i++) 48 { 49 if(i!=1)w+=t[i-1]; 50 q.push(a[w]);v.push(b[w]); 51 } 52 node1 n1=v.top(); 53 node n2=q.top(); 54 LL ans=n1.x-n2.x; 55 while(1) 56 { 57 node no=q.top(); 58 if(no.next==-1)break; 59 q.pop();q.push(a[no.next]);v.push(b[no.next]); 60 n1=v.top();n2=q.top(); 61 ans=min(ans,n1.x-n2.x); 62 } 63 printf("%lld\n",ans); 64 return 0; 65 }