日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問(wèn) 生活随笔!

生活随笔

當(dāng)前位置: 首頁(yè) > 编程资源 > 编程问答 >内容正文

编程问答

2018蓝桥杯模拟赛·青出于蓝而胜于蓝 DFS序+树状数组

發(fā)布時(shí)間:2023/12/10 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 2018蓝桥杯模拟赛·青出于蓝而胜于蓝 DFS序+树状数组 小編覺(jué)得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

武當(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(1n100000,1pn)。

接下來(lái) n?1n-1n?1 行,每行輸入兩個(gè)整數(shù) u,v(1≤u,v≤n)u, v(1 \le u, v \le n)u,v(1u,vn),表示 uuuvvv 之間存在師徒關(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)題。

如果覺(jué)得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。