讨论 / 大牛们来看看我第9个测试点怎么超时?应该怎么优化??
腾飞 2008-08-20 23:28:00
点我顶贴 收藏 删除
#include <iostream>

using namespace std;

unsigned long sum=0;

struct Link

{

unsigned long s;

Link *next;

};

void Insert(Link *&L,Link *Node)

{

Link *r,*q;

if(L==NULL)

{

L=Node;

L->next=NULL;

return;

}

if(Node->s<=L->s)

{

Node->next=L;

L=Node;

return;

}

r=L;

q=L->next;

while(q!=NULL)

{

if(Node->s>q->s)

{

r=q;

q=q->next;

}

else

break;

}

r->next=Node;

Node->next=q;

}

void make(Link *&L)

{

int da;

Link *r,*q,*p;

q=L;

if(L->next==NULL)

return;

p=new Link;

da=q->s+q->next->s;

sum+=da;

L=q->next->next;

delete q->next;

delete q;

p->s=da;

Insert(L,p);

make(L);

}

int main()

{

int n,t;

cin>>n;

Link *L=NULL,*Node=NULL;

while(n>0)

{

cin>>t;

Node=new Link;

Node->s=t;

Node->next=NULL;

Insert(L,Node);

n--;

}

make(L);

cout<<sum;

return 0;

}

#1 DarkMaster@2008-08-17 05:03:00
回复 删除
队列优化,用两个队列,一个队列保存未合并的,一个队列保存已经合并的。先把果子排序,全部放到一个队列中,每次从两个队里取出两个最小值合并,并放入已合并的队列中这样的做法是O(n)时间复杂度的。代码大致是这样:

program fruit(input,output);

type

arr=array[1..10000] of longint;

arr2=array[1..2,1..20000] of longint;

var

queue:arr2;

gz:arr;

open,head:array[1..2] of longint;

i,n,heapsize,ans:longint;

j,k:longint;

procedure maxheapfiy(var gz:arr; i:longint);

var

largest,l,r,tmp:longint;

begin

l:=i*2;

r:=i*2+1;

if (l<=heapsize)and(gz[l]>gz[i]) then largest:=l

else largest:=i;

if (r<=heapsize)and(gz[r]>gz[largest]) then largest:=r;

if largest<>i then begin

tmp:=gz[i]; gz[i]:=gz[largest]; gz[largest]:=tmp;

maxheapfiy(gz,largest);

end;

end;

procedure heapsort(var gz:arr);

var

i,tmp:longint;

begin

for i:=heapsize div 2 downto 1 do maxheapfiy(gz,i);

for i:=heapsize downto 2 do begin

tmp:=gz[i]; gz[i]:=gz[1]; gz[1]:=tmp;

dec(heapsize);

maxheapfiy(gz,1);

end;

end;

begin

fillchar(gz,sizeof(gz),0);

readln(n);

for i:=1 to n do read(gz[i]);

heapsize:=n;

heapsort(gz);

open[1]:=0; head[1]:=0; open[2]:=0; head[2]:=0;

for i:=1 to n do begin inc(open[1]); queue[1,open[1]]:=gz[i]; end;

ans:=0;

repeat

k:=0; j:=0;

if not((open[1]=head[1])and(open[2]=head[2])) then begin

if open[1]=head[1] then begin inc(head[2]); j:=queue[2,head[2]]; end

else if open[2]=head[2] then begin inc(head[1]); j:=queue[1,head[1]]; end

else

if queue[1,head[1]+1]>queue[2,head[2]+1] then begin inc(head[2]); j:=queue[2,head[2]]; end

else begin inc(head[1]); j:=queue[1,head[1]]; end;

end;

if not((open[1]=head[1])and(open[2]=head[2])) then begin

if open[1]=head[1] then begin inc(head[2]); k:=queue[2,head[2]]; end

else if open[2]=head[2] then begin inc(head[1]); k:=queue[1,head[1]]; end

else

if queue[1,head[1]+1]<queue[2,head[2]+1] then begin inc(head[1]); k:=queue[1,head[1]]; end

else begin inc(head[2]); k:=queue[2,head[2]]; end;

end;

ans:=ans+j+k;

if not((open[1]=head[1])and(open[2]=head[2])) then begin inc(open[2]); queue[2,open[2]]:=j+k; end;

until (open[1]=head[1])and(open[2]=head[2]);

write(ans);

end.

#2 @2008-08-20 23:27:00
回复 删除
队列优化,用两个队列,一个队列保存未合并的,一个队列保存已经合并的。先把果子排序,全部放到一个队列中,每次从两个队里取出两个最小值合并,并放入已合并的队列中这样的做法是O(n)时间复杂度的。

var i,j,x,y,ans,n,m,p,t,me,min:longint;

num:array[1..20000] of integer;

a,b:array[1..11000] of longint;

begin

readln(n);

for i:=1 to n do

begin

read(t);

inc(num[t])

end;

for i:=1 to 11000 do

begin

a[i]:=1000000000;

b[i]:=1000000000

end;

p:=0;

for i:=1 to 20000 do

for j:=1 to num[i] do

begin

inc(p);

a[p]:=i

end;{一个经典的排序}

x:=1;y:=1;ans:=0;

for i:=1 to n-1 do

begin

min:=maxlongint;

if a[x]+a[x+1]<min then begin min:=a[x]+a[x+1];me:=1 end;

if a[x]+b[y]<min then begin min:=a[x]+b[y];me:=2 end;

if b[y]+b[y+1]<min then begin min:=b[y]+b[y+1];me:=3 end;

b[i]:=min;

inc(ans,min);

if me=1 then inc(x,2);

if me=2 then begin inc(x);inc(y) end;

if me=3 then inc(y,2)

end;

writeln(ans)

end.

#3 @2008-08-20 23:28:00
回复 删除
队列优化,用两个队列,一个队列保存未合并的,一个队列保存已经合并的。先把果子排序,全部放到一个队列中,每次从两个队里取出两个最小值合并,并放入已合并的队列中这样的做法是O(n)时间复杂度的。

var i,j,x,y,ans,n,m,p,t,me,min:longint;

num:array[1..20000] of integer;

a,b:array[1..11000] of longint;

begin

readln(n);

for i:=1 to n do

begin

read(t);

inc(num[t])

end;

for i:=1 to 11000 do

begin

a[i]:=1000000000;

b[i]:=1000000000

end;

p:=0;

for i:=1 to 20000 do

for j:=1 to num[i] do

begin

inc(p);

a[p]:=i

end;{一个经典的排序}

x:=1;y:=1;ans:=0;

for i:=1 to n-1 do

begin

min:=maxlongint;

if a[x]+a[x+1]<min then begin min:=a[x]+a[x+1];me:=1 end;

if a[x]+b[y]<min then begin min:=a[x]+b[y];me:=2 end;

if b[y]+b[y+1]<min then begin min:=b[y]+b[y+1];me:=3 end;

b[i]:=min;

inc(ans,min);

if me=1 then inc(x,2);

if me=2 then begin inc(x);inc(y) end;

if me=3 then inc(y,2)

end;

writeln(ans)

end.

查看更多回复
提交回复