2018蓝桥杯模拟赛·青出于蓝而胜于蓝 DFS序+树状数组
武當(dāng)派一共有 nnn 人,門派內(nèi) nnn 人按照武功高低進(jìn)行排名,武功最高的人排名第 111,次高的人排名第 222,... 武功最低的人排名第 nnn。現(xiàn)在我們用武功的排名來(lái)給每個(gè)人標(biāo)號(hào),除了祖師爺,每個(gè)人都有一個(gè)師父,每個(gè)人可能有多個(gè)徒弟。
我們知道,武當(dāng)派人才輩出,連祖師爺?shù)奈涔Χ贾荒芘判械?ppp。也就是說(shuō)徒弟的武功是可能超過(guò)師父的,所謂的青出于藍(lán)勝于藍(lán)。
請(qǐng)你幫忙計(jì)算每個(gè)人的所有子弟(包括徒弟的徒弟,徒弟的徒弟的徒弟....)中,有多少人的武功超過(guò)了他自己。
輸入格式
輸入第一行兩個(gè)整數(shù) n,p(1≤n≤100000,1≤p≤n)n, p(1 \le n \le 100000, 1 \le p \le n)n,p(1≤n≤100000,1≤p≤n)。
接下來(lái) n?1n-1n?1 行,每行輸入兩個(gè)整數(shù) u,v(1≤u,v≤n)u, v(1 \le u, v \le n)u,v(1≤u,v≤n),表示 uuu 和 vvv 之間存在師徒關(guān)系。
輸出格式
輸出一行 nnn 個(gè)整數(shù),第 iii 個(gè)整數(shù)表示武功排行為 iii 的人的子弟有多少人超過(guò)了他。
行末不要輸出多余的空格。樣例輸入
10 5 5 3 5 8 3 4 3 1 2 1 6 7 8 7 9 8 8 10樣例輸出
0 0 2 0 4 0 1 2 0 0題意就是給我們一顆樹 讓我們求 每個(gè)點(diǎn)的所以所有孩子節(jié)點(diǎn)有多少比自己小的節(jié)點(diǎn)的數(shù)量 可以dfs下把所有節(jié)點(diǎn)的父節(jié)點(diǎn)找到 然后每個(gè)點(diǎn)不斷地向上找父節(jié)點(diǎn) 一直找到根 這樣的復(fù)雜度接近n的平方級(jí) 肯定超時(shí) 為了不超時(shí) 我們可以把整顆樹的DFS序搞出來(lái) 然后任意一個(gè)節(jié)點(diǎn)的先序和后序順序 中間的差就是這個(gè)點(diǎn)的孩子節(jié)點(diǎn)的個(gè)數(shù) 但是我們要找的是孩子節(jié)點(diǎn)中比他小的節(jié)點(diǎn) 那么我們就可以dfs序和樹狀數(shù)組配合起來(lái) dfs序把樹形問(wèn)題轉(zhuǎn)化成了區(qū)間上的問(wèn)題 我們知道這個(gè)點(diǎn)的先序和后序位次 那么如果有比他小的節(jié)點(diǎn)在這個(gè)節(jié)點(diǎn)的先序和后序之間遍歷到了 那么一定是符合要求的點(diǎn) 所以我們可以從小大到處理點(diǎn) 對(duì)于每個(gè)點(diǎn)查詢先序后序位置中樹狀數(shù)組存儲(chǔ)的差 然后再把當(dāng)前節(jié)點(diǎn)的先序插入進(jìn)去? 這樣的好處就是先遍歷標(biāo)號(hào)小的節(jié)點(diǎn) 先把小的節(jié)點(diǎn)的先序插到樹狀數(shù)組 樹狀數(shù)組維護(hù)的就是當(dāng)前節(jié)點(diǎn)先序插入時(shí)的次序 因?yàn)槲覀兪峭ㄟ^(guò)前序后序間符合條件的點(diǎn)數(shù)來(lái)求解的
import java.util.ArrayList; import java.util.Scanner; import java.util.Vector;public class Main {final static int maxn = 100010; public static int [] tre = new int[maxn];public static ArrayList<Integer>[] gra = new ArrayList[maxn];//存圖public static boolean[] bok = new boolean[maxn];public static boolean[] vis = new boolean[maxn];public static int[] l = new int[maxn];//記錄先序public static int[] r = new int[maxn];//記錄第二次回溯回來(lái)時(shí)的順序public static int time =0 ;static void DFS(int now) {l[now] = ++time;for(int i=0;i<gra[now].size();i++) {int t = gra[now].get(i);if(!vis[t]) {vis[t]=true;DFS(t);vis[t]=false;}}r[now] = time;}static void add(int x) {while(x<maxn) {tre[x]+=1;x+=x&(-x);}}static int sum(int x) {int S=0;while(x!=0) {S+=tre[x];x-=x&(-x);}return S;}public static void main(String[] args) {int n,p;Scanner sc = new Scanner(System.in);n = sc.nextInt();p = sc.nextInt();for(int i=1;i<n;i++) {int s,e;s = sc.nextInt();e = sc.nextInt();if(bok[s]==false) {bok[s] = true;gra[s] = new ArrayList<Integer>();gra[s].add(e);}else gra[s].add(e);if(bok[e]==false) {bok[e] = true;gra[e] = new ArrayList<Integer>();gra[e].add(s);}else gra[e].add(s);}vis[p]=true;DFS(p);for(int i=1;i<=n;i++) {System.out.print(sum(r[i])-sum(l[i]));add(l[i]);if(i==n)System.out.println();else System.out.print(" ");}} }
總結(jié)
以上是生活随笔為你收集整理的2018蓝桥杯模拟赛·青出于蓝而胜于蓝 DFS序+树状数组的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: 分享不可不知的CAD经典技巧
- 下一篇: 锡山国土推行数据中心“在线变更”