17.10.7B组总结

来源:互联网 发布:java开发重庆薪酬 编辑:程序博客网 时间:2024/05/20 05:53

17.10.7B组总结

今天的比赛如下所示:

=2

可惜我没AK,(⊙o⊙)…

T1

我自豪地表示我打了正解。
由于这题可以用二分,所以我一言不合用了二分,DP判断时发现仍有时超可能,且答案具有线性,于是我又用了单调队列。
判断过程:

function pd(x:longint):boolean;var        i,st,en,j:longint;        g,d:array[0..50000]of longint;begin        fillchar(g,sizeof(g),0);        fillchar(d,sizeof(d),0);        st:=1;        en:=1;        for i:=1 to n+1 do        begin                while (st<=en)and(d[st]<i-x-1) do                        inc(st);                g[i]:=g[d[st]]+a[i];                while (st<=en)and(g[d[en]]>g[i]) do                        dec(en);                inc(en);                d[en]:=i;        end;        if g[n+1]>t then                exit(false);        exit(true);end;

T2

第一眼看到这题,我便想到了曾经做过的——锻炼身体(https://jzoj.net/senior/#main/show/1753)
于是有了与此题类似的DP想法,设f[i,j,k]表示到了第i个时间段,j行k列的最大移动步数。方程显然。
听说正解用了单调队列,今天是单调队列专题?

uses math;var        n,m,x,y,k,i,j,l,ans,xx,yy,tot:longint;        a:array[0..200,0..200]of longint;        c:array[0..200,1..3]of longint;        f:array[0..201,0..200,0..200]of longint;        fx:array[0..4,1..2]of longint=((0,0),(-1,0),(1,0),(0,-1),(0,1));        ch:char;begin        readln(n,m,x,y,k);        for i:=1 to n do        begin                for j:=1 to m do                begin                        read(ch);                        if ch='.' then                                a[i,j]:=1;                end;                readln;        end;        f[1,x,y]:=1;        for i:=1 to k do        begin                readln(c[i,1],c[i,2],c[i,3]);                for j:=1 to n do                        for l:=1 to m do                                if f[i,j,l]<>0 then                                begin                                        f[i+1,j,l]:=max(f[i+1,j,l],f[i,j,l]);                                        xx:=j;                                        yy:=l;                                        tot:=0;                                        while true do                                        begin                                                inc(xx,fx[c[i,3],1]);                                                inc(yy,fx[c[i,3],2]);                                                inc(tot);                                                if (xx>0)and(yy>0)and(xx<=n)and(yy<=m)and(a[xx,yy]=1)and(tot-1<=c[i,2]-c[i,1]) then                                                        f[i+1,xx,yy]:=max(f[i+1,xx,yy],f[i,j,l]+tot)                                                else                                                        break;                                                ans:=max(ans,f[i+1,xx,yy]);                                        end;                                end;        end;        writeln(ans-1);end.

T3

比赛唯一没对的题,其实挺简单的,想到思路一码就过。
容易想到,对于两个点,最长边的最小值定在这个图的最小生成树上,于是我们可以删掉无用的边。接着再将这两个点到他们的LCA(最近公共祖先)找出来,答案就在这条路径上。

uses math;var        i,n,m,k,gx,gy,op,x,y,tot,j,r:longint;        a:array[0..30000,1..3] of longint;        fa,d:array[0..15000] of longint;        tov,next,last,len:array[0..80000] of longint;        f:array[0..80000,1..2] of longint;        g,wer:array[0..15000,0..16] of longint;procedure kp(l,r:longint);var        i,j,mid:longint;begin        i:=l;        j:=r;        mid:=a[(l+r) div 2,3];        repeat                while a[i,3]<mid do inc(i);                while a[j,3]>mid do dec(j);                if i<=j then                begin                        a[0]:=a[i];                        a[i]:=a[j];                        a[j]:=a[0];                        inc(i);                        dec(j);                end;        until i>j;        if l<j then kp(l,j);        if i<r then kp(i,r);end;function get(k:longint):longint;begin        if fa[k]=0 then                exit(k);        fa[k]:=get(fa[k]);        exit(fa[k]);end;procedure insert(x,y,z:longint);begin        inc(tot);        tov[tot]:=y;        len[tot]:=z;        next[tot]:=last[x];        last[x]:=tot;end;procedure dg(t,y:longint);var        i:longint;begin        d[t]:=d[y]+1;        i:=last[t];        while i<>0 do        begin                if tov[i]<>y then                begin                        dg(tov[i],t);                        f[tov[i],1]:=t;                        f[tov[i],2]:=len[i];                end;                i:=next[i];        end;end;function lca(x,y:longint):longint;var        k:longint;begin        lca:=-maxlongint;        while d[x]<d[y] do        begin                lca:=max(lca,f[y,2]);                y:=f[y,1];        end;        while d[x]>d[y] do        begin                lca:=max(lca,f[x,2]);                x:=f[x,1];        end;        while x<>y do        begin                lca:=max(lca,f[y,2]);                y:=f[y,1];                lca:=max(lca,f[x,2]);                x:=f[x,1];        end;end;begin        readln(n,m,k);        for i:=1 to m do                readln(a[i,1],a[i,2],a[i,3]);        kp(1,m);        for i:=1 to m do                if get(a[i,1])<>get(a[i,2]) then                begin                        insert(a[i,1],a[i,2],a[i,3]);                        insert(a[i,2],a[i,1],a[i,3]);                        gx:=get(a[i,1]);                        gy:=get(a[i,2]);                        fa[gx]:=gy;                end;        dg(1,0);        for i:=1 to k do        begin                readln(x,y);                writeln(lca(x,y));        end;end.
原创粉丝点击