膜拜一發\(mts\_246,forever\_shi\)
這兩位爺是真的無敵!
首先來看這個題,一看題目的資料範圍和「關鍵點」字眼,我們就能得知這是一道虛樹題
那就先一如既往的建出來虛樹吧
qwq但是這之後,應該怎麼去dp呢。
首先,我們需要知道在虛樹上每個點的從屬都是誰,這樣才便於我們進一步擴充套件到虛樹之外的點。
那麼怎麼求這個東西呢?我們可以先通過一編dfs,求出來子樹對父親的影響,也就是從下到上的答案(先\(dfs\)到底,再更新)
void dp1(int x,int flag)
for (int i=point[x];i;i=nxt[i]) }
}
然後呢,因為還存在說通過兄弟更新,或者子樹之外的點更新的情況,所以我們還需要重新\(dfs\)一遍,不過這次是嘗試通過用父親來更新兒子,也就是從上到下(先更新,後\(dfs\))
void dp2(int x,int flag)
dp2(p,flag);
}}
至此,我們就得到了所有虛樹上的點的\(dis\) 和 \(bel\),那怎麼擴充套件到所有點呢qwq
這裡就需要乙個奇妙的統計答案的技巧了
我們另\(ymh[i]\)表示與\(i\)相同議事處的點的個數。
首先,我們將初值弄成\(size[i]\),是i在原樹的子樹大小(這一定是不對的,因為子樹中有一些會和他的某個非直系子輩給包含,而他在上面的一片區域,也一定有和他一樣的點)
然後我們進行dfs
對於這個東西,顯然是要從下向上更新的
所以我們\(dfs\)到底,對於當前\(x->p\)這條邊,如果說兩個點的\(bel\)是相等的,我們就令\(ymh[x]-=size[p]\),相當於把原樹\(x->p\)這路徑附近部分所有的點,都給了\(x\),不論是合法還是不合法。
那麼上一種情況裡面不合法的情況,就是兩個點之間存在\(bel\)不一樣的點,也就是說,會存在一條邊\(x->p\),其中\(bel[x]!=bel[p]\),那麼這條路徑之間的東西應該怎麼算呢。
不難發現,一定是會存在說,這段路徑中間會有乙個點,以上全是屬於\(bel[x]\),以下全是屬於\(bel[p]\)的。
那麼我們可以通過倍增的方式來求出這個點(具體求的時候有一些細節,直接寫在**裡面了)
然後假設求出來的點是\(lyf\),那麼$$ymh[p]+=size[lyf]-size[p],ymh[x]-=size[lyf]$$
原理的話,和上面同理
這種用ymh陣列求解的方式,實際上就是先弄乙個初值,然後把不合法的(或者是會算重複的)減掉,然後把少算的加進去
qwq總之就是很巧妙!!!!!!!
既不會算少,也不會算重複
直接放**
#include#include#include#include#include#include#include#include#define mk makr_pair
#define ll long long
using namespace std;
inline int read()
while (isdigit(ch))
return x*f;
}const int maxn = 6e5+1e2;
const int maxm = 2*maxn;
const int inf = 1e9;
int point[maxn],nxt[maxm],to[maxm],val[maxm];
int bel[maxn],dis[maxn],f[maxn][21];
int num[maxn];
int size[maxn],deep[maxn],dfn[maxn];
int cnt,n,m;
int tot,top;
int s[maxn];
int k,a[maxn];
int ymh[maxn],tag[maxn];
int ans[maxn];
void addedge(int x,int y,int w)
void dfs(int x,int fa,int dep)
}void init()
}int go_up(int x,int d)
} return f[x][0];
} bool cmp(int a,int b)
else
else}}
}if (s[top]!=a[i]) s[++top]=a[i];
}while (top>1)
}void dp1(int x,int flag)
for (int i=point[x];i;i=nxt[i]) }
}void dp2(int x,int flag)
dp2(p,flag); }}
int up(int x,int d)
void dodo(int x)
ans[bel[p]]+=ymh[p];
} if (x==1) ans[bel[x]]+=ymh[x];
}int b[maxn];
int main()
dfs(1,0,1);
init();
memset(point,0,sizeof(point));
m=read();
for (int i=1;i<=m;i++)
return 0;
}
P3233 HNOI2014 世界樹(虛樹)
看到 mi 300000自然聯想到虛樹,簡單思考一下似乎可行,但剩下的部分貌似就比較麻煩。首先對重新構建的虛樹,考慮每個點應該被誰管。因為乙個點既可以被它子樹中的點管,也可以被子樹以外的點管,所以我們做兩次dfs。第一次先遍歷子節點,再更新,記錄的是乙個點子樹中最近的管他的點是誰。第二次先用從父節點...
洛谷P3237 HNOI2014 公尺特運輸
公尺特是d星球上一種非常神秘的物質,蘊含著巨大的能量。在以公尺特為主要能源的d星上,這種公尺特能源的運輸和儲 存一直是乙個大問題。d星上有n個城市,我們將其順序編號為1到n,1號城市為首都。這n個城市由n 1條單向高速 通道連線起來,構成一棵以1號城市 首部 為根的樹,高速通道的方向由樹中的兒子指向...
洛谷 2014 選課
在大學裡每個學生,為了達到一定的學分,必須從很多課程裡選擇一些課程來學習,在課程裡有些課程必須在某些課程之前學習,如高等數學總是在其它課程之前學習。現在有n門功課,每門課有個學分,每門課有一門或沒有直接先修課 若課程a是課程b的先修課即只有學完了課程a,才能學習課程b 乙個學生要從這些課程裡選擇m門...