17.11.25B组总结

17.11.25B组总结

T1

考试是打了2500+的暴力,30。
其实正解思路需要很有经验的选手才能想到,即将所有操作构为一棵树,再在树上进行递归暴力,对于还有20分一条链,会栈溢出,直接循环即可。
80分:

var
        a,b:array[0..1000000]of longint;
        tov,next,last,d,ch,y,ans:array[0..1000000]of longint;
        n,k,tot,i,z,t,bz:longint;
procedure insert(x,y:longint);
begin
        inc(tot);
        tov[tot]:=y;
        next[tot]:=last[x];
        last[x]:=tot;
end;
function find(l,r:longint):longint;
var
        mid:longint;
begin
        while l<r do
        begin
                mid:=(l+r) div 2;
                if d[mid]>=z then
                        r:=mid
                else
                        l:=mid+1;
        end;
        exit(r);
end;
procedure dfs(x:longint);
var
        i,yy:longint;
begin
        i:=last[x];
        while i>0 do
        begin
                yy:=tov[i];
                i:=next[i];
                if a[yy]=0 then
                begin
                        if b[yy]>d[t] then
                        begin
                                inc(t);
                                d[t]:=b[yy];
                                ch[yy]:=t;
                                y[yy]:=0;
                        end
                        else
                        begin
                                z:=b[yy];
                                k:=find(1,t);
                                y[yy]:=d[k];
                                ch[yy]:=k;
                                d[k]:=b[yy];
                        end;
                end
                else
                        ch[yy]:=0;
                ans[yy]:=t;
                dfs(yy);
        end;
        if ch[x]=0 then
                exit;
        d[ch[x]]:=y[x];
        if (ch[x]=t)and(y[x]=0) then
                dec(t);
end;
begin
        readln(n);
        d[0]:=-maxlongint;
        t:=0;
        for i:=1 to n do
        begin
                readln(a[i],b[i]);
                if a[i]=0 then
                        insert(i-1,i)
                else
                        insert(b[i],i);
        end;
        dfs(0);
        for i:=1 to n do
                writeln(ans[i]);
end.

另外20:

var
        a,b:array[0..1000000]of longint;
        tov,next,last,d,ch,y,ans:array[0..1000000]of longint;
        n,k,tot,i,z,t,bz:longint;
procedure insert(x,y:longint);
begin
        inc(tot);
        tov[tot]:=y;
        next[tot]:=last[x];
        last[x]:=tot;
end;
function find(l,r:longint):longint;
var
        mid:longint;
begin
        while l<r do
        begin
                mid:=(l+r) div 2;
                if d[mid]>=z then
                        r:=mid
                else
                        l:=mid+1;
        end;
        exit(r);
end;
begin
        readln(n);
        d[0]:=-maxlongint;
        t:=0;
        for i:=1 to n do
                readln(a[i],b[i]);
        for i:=1 to n do
        begin
                if a[i]=0 then
                begin
                        if b[i]>d[t] then
                        begin
                                inc(t);
                                d[t]:=b[i];
                                ch[i]:=t;
                                y[i]:=0;
                        end
                        else
                        begin
                                z:=b[i];
                                k:=find(1,t);
                                y[i]:=d[k];
                                ch[i]:=k;
                                d[k]:=b[i];
                        end;
                end
                else
                        ch[i]:=0;
                writeln(t);
        end;
end.

T2

考试时理解错题意,爆0。
正解有四个数组,递推。每次将 (i+1)3,(i+1)2 (i+1) 维护,再每次更新DP数组 f[i]:=f[i1]+f3[i]f3[i1]x

var
        n,i,j:longint;
        f,f1,f2,f3:array[0..100000]of extended;
        x:extended;
begin
        readln(n);
        for i:=1 to n do
        begin
                readln(x);
                f1[i]:=(f1[i-1]+1)*x;
                f2[i]:=(f2[i-1]+f1[i-1]*2+1)*x;
                f3[i]:=(f3[i-1]+f2[i-1]*3+f1[i-1]*3+1)*x;
                f[i]:=f[i-1]+f3[i]-x*f3[i-1];
        end;
        writeln(f[n]:0:1);
end.

T3

最简单的一题,先用SPFA维护出k个点互相之间的距离,再DFS即可。
注意初值稍微大一点,判断-1。

var
        que,next,last,len,tov,dis:array[0..100000]of longint;
        exist:array[0..100000]of boolean;
        dist:array[0..15,0..15]of int64;
        g,bz:array[0..15]of longint;
        head,tail,n,m,i,x,y,z,tot,k,s,t:longint;
        ans:int64;
procedure insert(x,y,z:longint);
begin
        inc(tot);
        tov[tot]:=y;
        len[tot]:=z;
        next[tot]:=last[x];
        last[x]:=tot;
end;
procedure spfa(cc,c:longint);
var
        x,y,i:longint;
begin
        fillchar(que,sizeof(que),0);
        fillchar(exist,sizeof(exist),0);
        fillchar(dis,sizeof(dis),0);
        que[1]:=c;
        exist[c]:=true;
        head:=0;
        tail:=1;
        for i:=1 to n do
                dis[i]:=maxlongint div 2;
        dis[c]:=0;
        while head<>tail do
        begin
                head:=head mod n+1;
                x:=que[head];
                i:=last[x];
                while i<>0 do
                begin
                        y:=tov[i];
                        if dis[y]>dis[x]+len[i] then
                        begin
                                dis[y]:=dis[x]+len[i];
                                if not exist[y] then
                                begin
                                        tail:=tail mod n+1;
                                        que[tail]:=y;
                                        exist[y]:=true;
                                end;
                        end;
                        i:=next[i];
                end;
                exist[x]:=false;
        end;
        for i:=0 to k+1 do
                dist[cc,i]:=dis[g[i]];
end;
procedure dg(x,ge:longint;sum:int64);
var
        i:longint;
begin
        if sum>=ans then
                exit;
        if ge=k+1 then
        begin
                inc(sum,dist[x,k+1]);
                if sum>=ans then
                        exit;
                ans:=sum;
                exit;
        end;
        for i:=0 to k do
                if (bz[i]=0)and(sum+dist[x,i]<ans) then
                begin
                        bz[i]:=1;
                        dg(i,ge+1,sum+dist[x,i]);
                        bz[i]:=0;
                end;
end;
begin
        readln(n,m,k,s,t);
        for i:=1 to m do
        begin
                readln(x,y,z);
                insert(x,y,z);
        end;
        g[0]:=s;
        g[k+1]:=t;
        for i:=1 to k do
                readln(g[i]);
        fillchar(dist,sizeof(dist),63);
        for i:=0 to k+1 do
                spfa(i,g[i]);
        bz[0]:=1;
        ans:=maxlongint*2;
        dg(0,1,0);
        if ans=1073741823 then
                writeln(-1)
        else
                writeln(ans);
end.

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值