1. 程式人生 > >17.8.15第七次測試

17.8.15第七次測試

道路 例如 遵從 span 滿足 公式 調試 fin binary

1.二叉樹

技術分享

技術分享
【問題描述】
二叉排序樹或者是一棵空樹,或者是具有下列性質的二叉樹:
(1)若左子樹不空,則左子樹上所有結點的值均小於它的根結點的值;
(2)若右子樹不空,則右子樹上所有結點的值均大於它的根結點的值;
(3)左、右子樹也分別為二叉排序樹;
(4)沒有鍵值相等的結點。
完全二叉樹:只有最下面的兩層結點度能夠小於2,並且最下面一層的結點
都集中在該層最左邊的若幹位置的二叉樹。
上圖中,(a)和(b)是完全二叉樹,(c)和(d)是非完全二叉樹。
給出N個數,且這N個數構成1至N的排列。現在需要你按順序構建一棵二叉
排序樹,並按照層次遍歷的方式輸出它,然後判斷它是否是一棵完全二叉樹。
【輸入格式】
輸入文件名為binary.
in。 輸入文件包含兩行。第一行為一個正整數N;第二行為1至N的排列。 【輸出格式】 輸出文件名為binary.out。 輸出文件包含兩行。第一行為構建出的二叉排序樹的層次遍歷;第二行判 斷是否是完全二叉樹:若是輸出yes,否則輸出no。 【輸入輸出樣例1】 binary.in 10 7 9 8 4 6 2 10 1 5 3 binary.out 7 4 9 2 6 8 10 1 3 5 yes 【輸入輸出樣例2】 binary.in 5 3 4 5 2 1 binary.out 3 2 4 1 5 no 【數據規模與約定】 對於100%的數據,1≤N≤20
View Code

技術分享

題解:基本的二叉樹,讀入x,然後從根節點開始,小就放左,大就放右,滿了就放下一層。

判斷是否完全其實很容易,一個x個節點的樹如果是完全二叉樹,它的1-x號節點都是非空的,這個調試一下就可以發現。

一開始錯了其實是自己粗心,只輸出了前x個節點,但是如果這顆樹不是完全的,就會有未輸出的情況,光榮的貢獻一個wa。

代碼:

技術分享
#include<cstdio>
#include<cstring>
#include<algorithm>
#define maxn 2100000
using namespace std;
int tree[maxn];
int a[25],n,flg;

void build(int x){
    int i=1;
    
while(1){ if(x<tree[i]){ if(!tree[i<<1]){ tree[i<<1]=x; break; } i<<=1; } if(x>tree[i]){ if(!tree[i<<1|1]){ tree[i<<1|1]=x; break; } i=i<<1|1; } } } int main(){ freopen("binary.in","r",stdin); freopen("binary.out","w",stdout); scanf("%d",&n); flg=1; for(int i=1;i<=n;i++){ scanf("%d",&a[i]); } tree[1]=a[1]; for(int i=2;i<=n;i++)build(a[i]); for(int i=1;i<=maxn;i++){ if(!tree[i]){ if(i<=n) flg=0; } else printf("%d ",tree[i]); } if(flg)printf("\nyes"); else printf("\nno"); }
View Code

2.列車調度

技術分享
【問題描述】
有N輛列車,標記為1,2,3,…,N。它們按照一定的次序進站,站臺共有K個軌
道,軌道遵從先進先出的原則。列車進入站臺內的軌道後可以等待任意時間後出
站,且所有列車不可後退。現在要使出站的順序變為N,N-1,N-2,…,1,詢問K的
最小值是多少。
例如上圖中進站的順序為1,3,2,4,8,6,9,5,7,則出站的順序變為
9,8,7,6,5,4,3,2,1。
【輸入格式】
輸入文件名為manage.in。
輸入共2行。
第 1 行包含1個正整數N,表示N輛列車。
第 2 行包含N個正整數,為1至N的一個排列,表示進站次序。
【輸出格式】
輸出文件名為manage.out。
輸出共1行,包含1個整數,表示站臺內軌道數K的最小值。
【輸入輸出樣例1】
manage.in 
3
1 2 3

manage.out
3
【輸入輸出樣例2】
manage.in 
9
1 3 2 4 8 6 9 5 7

manage.out
5

【數據規模與約定】
對於 30%的數據,N≤10;
對於 70%的數據,N≤2000;
對於 100%的數據,N≤100000
View Code

技術分享

題解:這題和codevs上的攔截導彈很像,只要之前有軌道最後一輛車編號比當前的大,就把當前的車停在那。但是如果有多個符合條件,找與當前差最小的一個(這樣如果再來一輛編號大的,就可以停在那些末尾較大的軌道裏,保證軌道利用高效。舉例:當前兩個軌道,末尾分別為5,3;來了一輛編號1的車,就停在3後。因為若停在5後,若下一輛為4,則就要新開軌道造成浪費了。)。如果沒有符合的軌道,則所需軌道+1。

因為數據比較水原因,可以用以上方法暴力過,但是如果是一般情況,100000輛車,如果軌道數較大,是需要二分的。把當前所有軌道末尾放在數組裏進行二分求相差最近的軌道。

代碼:

技術分享
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
int ans,top,n,a[200005],q[200005];
int main()
{
    freopen("manage.in","r",stdin);
    freopen("manage.out","w",stdout);
    scanf("%d",&n);
    for(int i=1;i<=n;i++)
        scanf("%d",&a[i]);
    int l=1,r=1;
    top=1;
    q[l]=a[1];
    for(int i=2;i<=n;i++){
        l=0;r=top;
        if(a[i]>q[top]){
            top++;
            q[top]=a[i];
            continue;
        }
        while(r-l>1){
            int m=(l+r)>>1;
            if(q[m]<a[i])l=m;
            else r=m;
        }
        q[r]=a[i];
    }
    printf("%d",top);
    return 0;
}
View Code

3. 保留道路

技術分享
【問題描述】
很久很久以前有一個國家,這個國家有N個城市,城市由1,2,3,…,N標號,
城市間有M條雙向道路,每條道路都有兩個屬性g和s,兩個城市間可能有多條道
路,並且可能存在將某一城市與其自身連接起來的道路。後來由於戰爭的原因,
國王不得不下令減小花費從而關閉一些道路,但是必須要保證任意兩個城市相互
可達。
道路花費的計算公式為wG*max{所有剩下道路的屬性g}+wS*max{所有剩下道
路的屬性s},其中wG和wS是給定的值。國王想要在滿足連通性的前提下使這個花
費最小,現在需要你計算出這個花費。
【輸入格式】
輸入文件名為road.in。
第一行包含兩個正整數N和M。
第二行包含兩個正整數wG和wS。
後面的M行每行描述一條道路,包含四個正整數u,v,g,s,分別表示道路連接
的兩個城市以及道路的兩個屬性。
【輸出格式】
輸出文件名為road.out。
輸出一個整數,表示最小花費。若無論如何不能滿足連通性,輸出-1。
【輸入輸出樣例】
road.in
3 3
2 1
1 2 10 15
1 2 4 20
1 3 5 1

road.out
30
【數據規模與約定】
對於 10%的數據,N≤10,M≤20;
對於 30%的數據,N≤100,M≤1000;
對於 50%的數據,N≤200,M≤5000;
對於 100%的數據,N≤400,M≤50000,wG,wS,g,s≤1000000000
View Code

題解:

這題乍一看很沒思路(所以考試沒做出來qaq)。但是仔細分析一下還是很有意思。

本題的難點在於它的排序有兩個參數要考慮,讓人排序的時候無從下手。不過仔細考慮一下,可以發現,我們可以先從一個參數下手。

先將所有道路按g從小到大排序,然後建立一個最小生成樹有n條邊,以s的值把邊的編號放進數組st中,再依次把其他邊加入這個數組,不難知道,新的最小值一定會從每次的n+1條邊中更新而來。

然後每次把st中最上面的點去掉,保留n條邊,這樣每次都從n+1條裏找樹,每次和ans取最小,就是答案。

代碼:

技術分享
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
using namespace std;
#define ll long long
const int N=410;
const int M=50010;
int n,m,i,j,num,fu,fv;
ll Wg,Ws;
struct edge
{
    int u,v,g,s;
}a[M];

ll ans=0x7fffffffffffffffLL;
int fa[N],st[N],top;

int find(int x)
{
    return fa[x]==x?x:fa[x]=find(fa[x]);
}

int cmp(edge a,edge b){
    return a.g<b.g;
}

int main(){
    freopen("road.in","r",stdin);
    freopen("road.out","w",stdout);
    scanf("%d%d",&n,&m);
    scanf("%d%d",&Wg,&Ws);
    for(i=1;i<=m;i++){
        scanf("%d%d%d%d",&a[i].u,&a[i].v,&a[i].g,&a[i].s);
    }
    sort(a+1,a+m+1,cmp);
    top=0;
    for(i=1;i<=m;i++){
        for(j=1;j<=n;j++)fa[j]=j;
        for(j=top;j>=1;j--){
            if(a[st[j]].s>a[i].s){
                st[j+1]=st[j];
            }
            else break;
        }
        top++;
        st[j+1]=i;
        num=0;
        for(j=1;j<=top;j++){
            fu=find(a[st[j]].u);fv=find(a[st[j]].v);
            if (fu!=fv)
            {
                fa[fu]=fv;
                st[++num]=st[j];
            }
        }
        if (num==n-1)
            ans=min(ans,Wg*a[i].g+Ws*a[st[num]].s);
        top=num;
    }
    if (ans==0x7fffffffffffffffLL)printf("-1\n");
    else printf("%I64d\n",ans);
    return 0;
}
View Code

17.8.15第七次測試