Jumping Monkey(CCPC网络赛重赛)
生活随笔
收集整理的這篇文章主要介紹了
Jumping Monkey(CCPC网络赛重赛)
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
Jumping Monkey(CCPC網絡賽重賽)
題意:
n個點的樹,每個點有一個不同的值aia_iai?.現在一個猴子在樹上,這個猴子從點u跳到點v當且僅當ava_vav?是u到v最短路徑上的最大值。如果沒有點能跳將停止。
對于k∈[1,n],計算猴子在點k開始最多能跳的點數量
題解:
每次跳躍點u,u要是路徑上的最大值。如果點權最大的那個節點(設為u),顯然無論從哪里開始跳,都可以直接到達u,且無法越過u到達其他點,到達u后也不能再跳向其他結點。也就是說u是最優方案中最后一個到達的點。那u的位置已經被固定了,將u從樹上去掉,對剩下的每個連通塊都遞歸上述過程,這樣確定的新樹,深度就是其答案。
但是上述的遞歸不好實現,我們逆向考慮這個過程:我們將點權按照從小到大枚舉,當前枚舉到點u,將u作為所有與u相連的(必須是已經枚舉過的,也就是點權比u小的)連通塊的跟。這樣得到的一顆新樹,u是v的父親,說明u的點權大于v,其原樹中u與v之間存在邊,那v就是到達它的所有父親點,所以每個節點的深度就是答案
復雜度O(nlog n)
代碼:
#include <bits/stdc++.h> #include <unordered_map> #define debug(a, b) printf("%s = %d\n", a, b); using namespace std; typedef long long ll; typedef unsigned long long ull; typedef pair<int, int> PII; clock_t startTime, endTime; //Fe~Jozky const ll INF_ll= 1e18; const int INF_int= 0x3f3f3f3f; void read(){}; template <typename _Tp, typename... _Tps> void read(_Tp& x, _Tps&... Ar) {x= 0;char c= getchar();bool flag= 0;while (c < '0' || c > '9')flag|= (c == '-'), c= getchar();while (c >= '0' && c <= '9')x= (x << 3) + (x << 1) + (c ^ 48), c= getchar();if (flag)x= -x;read(Ar...); } template <typename T> inline void write(T x) {if (x < 0) {x= ~(x - 1);putchar('-');}if (x > 9)write(x / 10);putchar(x % 10 + '0'); } void rd_test() { #ifdef ONLINE_JUDGE #elsestartTime = clock ();freopen("data.in", "r", stdin); #endif } void Time_test() { #ifdef ONLINE_JUDGE #elseendTime= clock();printf("\nRun Time:%lfs\n", (double)(endTime - startTime) / CLOCKS_PER_SEC); #endif } const int maxn=2e5+9; PII val[maxn]; bool vis[maxn]; int fa[maxn]; vector<int>vec[maxn]; vector<int>g[maxn]; int dep[maxn]; int find(int x){if(fa[x]==x)return x;return fa[x]=find(fa[x]); } void dfs(int u){for(auto v:g[u]){dep[v]=dep[u]+1;dfs(v);} } int main() {//rd_test();int t;read(t);while(t--){int n;cin>>n;for(int i=1;i<=n;i++)vis[i]=0;for(int i=1;i<=n;i++)fa[i]=i;for(int i=1;i<n;i++){int u,v;read(u,v);vec[u].push_back(v);vec[v].push_back(u);}for(int i=1;i<=n;i++){read(val[i].first);val[i].second=i;}sort(val+1,val+1+n);for(int i=1;i<=n;i++){int u=val[i].second;vis[u]=1;for(auto v:vec[u]){if(vis[v]==0)continue;int fv=find(v);fa[fv]=u;g[u].push_back(fv);}}dep[val[n].second]=1;dfs(val[n].second);for(int i=1;i<=n;i++)cout<<dep[i]<<endl;for(int i=0;i<=n;i++){g[i].clear(); vec[i].clear();}}return 0;//Time_test(); }總結
以上是生活随笔為你收集整理的Jumping Monkey(CCPC网络赛重赛)的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: 发烧了可以泡脚吗
- 下一篇: Bigraph Extension