luogu1631 序列合并

题目

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

题解

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

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

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

代码(TLE)

include

include

include

include

include

define N 100005

using namespace std;

int n,a[N],b[N],ans[N];
priority_queue 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

include

include

include

include

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  阅读(158)  评论(0)    收藏  举报