看到∑mi≤300000自然聯想到虛樹,簡單思考一下似乎可行,但剩下的部分貌似就比較麻煩。
首先對重新構建的虛樹,考慮每個點應該被誰管。因為乙個點既可以被它子樹中的點管,也可以被子樹以外的點管,所以我們做兩次dfs。第一次先遍歷子節點,再更新,記錄的是乙個點子樹中最近的管他的點是誰。第二次先用從父節點得到的資料更新,再遍歷子節點,是把子樹之外可以管他的點也考慮進去。在第二次dfs時我們可以順便統計一部分貢獻,就是對於節點i,如果它其中乙個子節點的子樹不在虛樹內,那這棵子樹中一定沒有可以管別人的點,那麼顯然,這棵子樹中所有點都和節點i被同乙個點管。
然後還有一部分沒有統計,就是虛樹的一條邊上實際點,以及他們那些不在虛樹上的子樹。那麼我們再dfs一次,如果一條邊的兩個節點被同乙個點管,那沒有問題;如果不是,我這個程式預設中間的所有點都和深度小的節點被同乙個點管,我們需要修正一下。我們可以用倍增找到中間的分界點,然後重新統計這一段的貢獻。
大概就是這樣啦~
#include#include#includeusing namespace std;
const int n=300010;
struct edgedata[n<<1],data1[n];
struct querya1[n];
bool flag[n];
int n,q,m,num,num1,num2,h[n],h1[n],ans[n],dep[n],dfn[n],siz[n],fa[n][20],sta[n],top,dis[n],c1[n];
inline int read()
inline void addedge(int u,int v)
inline void addedge1(int u,int v)
inline bool cmp1(query a,query b)
inline int getx(int u,int x)
}void dfs3(int u,int t,int d)else
sta[++top]=a1[j].x;
} while(top>1)addedge1(sta[top-1],sta[top]),--top;
dfs2(1);dfs3(1,0,n);dfs4(1);
sort(a1+1,a1+m+1,cmp2);
for(int j=1;j<=m;++j)
printf("\n");
} return 0;
}
題解 HNOI 2014 世界樹
洛谷 bzoj loj 題目概要 給定一棵 n n 個節點的樹,q role presentation q q次詢問 給定 m m 個關鍵點,每個原樹上的點被最近且序號最小的關鍵點控制,問每個關鍵點 n,q,m 300000 role presentation n,q m 300000n,q,m 3...
題解 HNOI2014 世界樹
hnoi2014 世界樹 從資料範圍很容易看出是個虛樹dp 可惜看出來了也還是不會做 虛樹大家應該都會,不會的話自己去搜吧,我懶得講了,我們在這裡只需要考慮如何dp即可 首先我們需要求出每個點被哪個點所控制,設 u 點被 bl u 所控制,兩遍dfs即可,考慮兒子對父親的影響和父親對兒子的影響 細節...
虛數 BZOJ3572 HNOI2014 世界樹
給出一顆樹,每次選中m個點,對於樹上任意乙個點,會被其最近的乙個選中點包含 相同有編號小優先 求每個選中點包含了多少個點。之前寫過兩次都沒寫部落格。結果複習板題的時候,連題意都不知道。方法就是虛數板子 include include include include define sf scanf d...