17.8.15第七次測試
阿新 • • 發佈:2017-08-19
道路 例如 遵從 span 滿足 公式 調試 fin binary
1.二叉樹
【問題描述】 二叉排序樹或者是一棵空樹,或者是具有下列性質的二叉樹: (1)若左子樹不空,則左子樹上所有結點的值均小於它的根結點的值; (2)若右子樹不空,則右子樹上所有結點的值均大於它的根結點的值; (3)左、右子樹也分別為二叉排序樹; (4)沒有鍵值相等的結點。 完全二叉樹:只有最下面的兩層結點度能夠小於2,並且最下面一層的結點 都集中在該層最左邊的若幹位置的二叉樹。 上圖中,(a)和(b)是完全二叉樹,(c)和(d)是非完全二叉樹。 給出N個數,且這N個數構成1至N的排列。現在需要你按順序構建一棵二叉 排序樹,並按照層次遍歷的方式輸出它,然後判斷它是否是一棵完全二叉樹。 【輸入格式】 輸入文件名為binary.View Codein。 輸入文件包含兩行。第一行為一個正整數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。
題解:基本的二叉樹,讀入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;View Codewhile(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"); }
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第七次測試