luogu1631 序列合并

题目

https://www.luogu.org/problem/show?pid=1631

题解

应该是我的方法不是很优,这道题系统堆也是可以过的,但是我的过不掉

那就干脆以这道题为例,比较一下系统堆和手写堆的速度

方法就是先将b[1]与a[i]逐个相加,先全部push到堆里,再从2~n枚举b,依次与a中的数相加后与堆顶比较,若较小则更新堆中元素,若较大直接break(因为a是有序的,若当前值与b[i]相加大于堆顶,后面的一定均大于,无须比较),最后从小到大输出堆中元素

代码(TLE)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath> 
#include <queue> 
#define N 100005
using namespace std; 

int n,a[N],b[N],ans[N];
priority_queue<int> q;

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    for(int i=1;i<=n;i++) q.push(a[i]+b[1]);
    for(int i=2;i<=n;i++)
    {
        int j=1;
        for(j;j<=n;j++)
        {
            int k=q.top();
            if(b[i]+a[j]<k) {q.pop();q.push(b[i]+a[j]);}
            else break;
        }
        if(j==1) break;
    }
    for(int i=1;i<=n;i++) {ans[i]=q.top();q.pop();}
    for(int i=n;i>=1;i--) printf("%d ",ans[i]);
    return 0;
}

image

直接使用系统堆,可以得90分,并且第八九个点时长就比较大了

代码(AC)

#include <iostream>
#include <cstdio>
#include <algorithm>
#include <cmath> 
#include <queue> 
#define inf 2147483646
#define N 1000005
using namespace std; 

int n,a[N],b[N],ans[N];
int q[N],sz;

void push(int x)
{
    q[++sz]=x;
    int pos=sz;
    while(pos>1&&q[pos>>1]<q[pos])
        swap(q[pos],q[pos>>1]),pos=pos>>1;
}

void pop()
{
    int rt=q[sz--],pos=1;
    q[pos]=rt;
    while(true)
    {
        int lv=(pos<<1)>sz? -inf:q[pos<<1];
        int rv=(pos<<1|1)>sz? -inf:q[pos<<1|1];
        int v=max(lv,rv),nt=lv>rv? (pos<<1):(pos<<1|1);
        if(q[pos]<v)
            swap(q[pos],q[nt]),pos=nt;
        else break;
    }
}

int top() {return q[1];}

int main()
{
    scanf("%d",&n);
    for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    for(int i=1;i<=n;i++) scanf("%d",&b[i]);
    for(int i=1;i<=n;i++) push(a[i]+b[1]);
    for(int i=2;i<=n;i++)
    {
        int j=1;
        for(j;j<=n;j++)
        {
            int k=top();
            if(b[i]+a[j]<k) {pop();push(b[i]+a[j]);}
            else break;
        }
        if(j==1) break;
    }
    for(int i=1;i<=n;i++) {ans[i]=top();pop();}
    for(int i=n;i>=1;i--) printf("%d ",ans[i]);
    return 0;
}

image

仅将系统堆改为手写堆,就A掉了此题,并且速度改善非常大

总结

在不开优化的情况下,C++STL的很多函数速度非常不理想,尽量手打

posted @ 2017-08-15 09:25  XYZinc  阅读(144)  评论(0编辑  收藏  举报