洛谷P1631序列合并(二分答案经典好题,或优先队列堆)

题目链解:https://www.luogu.org/problemnew/show/P1631

这题刚看完有点蒙,两个for循环的话不但爆空间,也爆时间啊!

看了大佬解释后,发现有2种做法,二分答案或优先队列(堆)。个人倾向于二分答案。

想到二分答案并不容易,有3点关键:

1.题目给的是有序的!

2.从小达到排,找到最大的停止!(最大值!关键二分)

3.这是一个范围问题,最小范围和最大范围上限已知!(明显二分!)

(选n个数,也就是n次,和移动石头m一样的。。)

另外需要注意的是,第一个for循环枚举答案的时候,完全可以找到一个点跳出达到很大的剪枝优化!(后面肯定不会有更小的了就退出完成)

 1 #include<iostream>
 2 #include<algorithm>
 3 using namespace std;
 4 const int maxn=1e6;
 5 int a[maxn],b[maxn];
 6 int c[maxn];//结果数组要开大,因为可能有重复
 7 int n;
 8 
 9 int judge(int x)
10 {
11     int cnt=0;
12     for(int i=1;i<=n;i++)
13     {
14         if(cnt>n) break;//数选够了退出
15         if(a[i]+b[1]>x) break;//这个优化很重要(整个循环退出),不用枚举到底了,如果第i个数+b第一个都比x大后面(包括下一轮)肯定所有更大!
16                               //这个>和j循环里的>意义不同更重大,j循环里的>退出,下一轮可能还有更小的!但第一个>退出就代表下一轮也不可能更小了!
17         for(int j=1;j<=n;j++)
18         {
19             if(a[i]+b[j]<x)//选了这个数,数的个数+1
20             {
21                 cnt++;
22                 if(cnt>n) break;
23             }
24             else if(a[i]+b[j]>x) break;//>这一轮退出(因为下一轮可能有更小的)
25         }
26     }
27     
28     return cnt;
29 }
30 
31 int main()
32 {
33     ios::sync_with_stdio(false); cin.tie(0);
34     
35     cin>>n;
36     for(int i=1;i<=n;++i) cin>>a[i];
37     for(int i=1;i<=n;++i) cin>>b[i];
38 
39     int l=a[1]+b[1],r=a[n]+b[n];
40     int ans=0;
41     while(l<=r)
42     {
43         int mid=(l+r)/2;
44         
45         int t=judge(mid);
46         if(t<=n)
47         {
48             l=mid+1;
49             ans=mid;
50         }
51         else r=mid-1;
52     }
53     
54     int p=0;
55     for(int i=1;i<=n;++i)
56     {
57         if(a[i]+b[1]>ans) break;//和judge里优化一样不再重述
58         for(int j=1;j<=n;++j)
59         {
60             if(a[i]+b[j]<=ans)
61             {
62                 c[++p]=a[i]+b[j];
63             }
64             else break;
65         }
66     }
67     sort(c+1,c+1+p);
68 
69     for(int i=1;i<=n-1;i++) cout<<c[i]<<" ";
70     cout<<c[n]<<endl;
71     
72     return 0;
73 }

完。

猜你喜欢

转载自www.cnblogs.com/redblackk/p/9933431.html