洛谷P6033 [NOIP2004 提高组] 合并果子 加强版 (单调队列)

数据加强了,原来nlogn的复杂度就不行了......

首先对原来的n个数排序(注意不能用快排),因为值域是1e5,所以可以开桶排序,开两个队列,一个存原来的n个数(已经满足单增),另一队列存两两合并后的数(也是满足单调性的),每次合并从两个队列中选取最小的两个数,合并后放入第二个队列就行了。

更难的题目还是蚯蚓,其中隐晦的单调性与此类似。

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define int long long
 4 queue<int>q1;
 5 queue<int>q2;
 6 int n,to[100005];//to[]是桶 
 7 
 8 int read(){
 9     int x=0,f=1;char c=getchar();
10     while(c<'0'||c>'9') {if(c=='-') f=-1;c=getchar();}
11     while(c>='0'&&c<='9') x=(x<<3)+(x<<1)+(c^48),c=getchar();
12     return x*f;
13 }
14 
15 signed main(){
16     n=read();
17     for(int i=1;i<=n;i++){
18         int a;a=read();
19         to[a]++;
20     }
21     for(int i=1;i<=100000;i++){
22         while(to[i]){
23             to[i]--;
24             q1.push(i);
25         }
26     }
27     int ans=0;
28     for(int i=1;i<=n-1;i++){//合并n-1次 
29         int x,y;
30         if((q1.front()<q2.front()&&!q1.empty())||q2.empty()){
31             x=q1.front();
32             q1.pop();
33         }
34         else{
35             x=q2.front();
36             q2.pop();
37         }
38         if((q1.front()<q2.front()&&!q1.empty())||q2.empty()) {
39             y=q1.front();
40             q1.pop();
41         }
42         else{
43             y=q2.front();
44             q2.pop();
45         }
46         ans+=x+y;
47         q2.push(x+y);
48     }
49     printf("%lld\n",ans);
50     return 0;
51 }

 

posted @ 2022-06-11 14:46  YHXo  阅读(86)  评论(0编辑  收藏  举报