NOIP2016 天天愛跑步

2022-05-07 20:30:15 字數 1996 閱讀 5462

真\(™\)是\(noip\)近幾年中最難的一道……

先看一下部分分,有起點終點為根節點的分值,想到拆路徑,對於路徑\((s,t)\),拆為\((s,lca)\)和\((t,lca)\)。

首先明確一點,可能有多條路徑有相同的起點,\(lca\)或終點。

先考慮\((s,lca)\)這一半,一條路徑只會對路徑上的點產生貢獻,不妨設有乙個點\(x\)在這一半上。

則這條路徑對\(x\)有貢獻,當且僅當滿足\(d[u]=w[x]+d[x]\)時,發現對於乙個點(觀察員),\(w[x]+d[x]\)為定值。

對於乙個點\(x\),一條路徑對其有貢獻當且僅當這條路徑的\(lca\)為\(x\)或這條路徑僅有乙個端點在\(x\)的子樹中(這樣的路徑\(lca\)在\(x\)之上)

如圖,藍色和綠色的路徑會產生貢獻,而紅色則不會。所以我們可以\(dfs\)統計答案,即檢視有多少個在\(x\)的子樹中的路徑起點的\(d[u]\)等於\(w[x]+d[x]\),這樣統計出的答案只會多不會少,我們考慮如何去掉多餘的答案。

先看一下實現過程,先開乙個\(bag\)記錄像\(d[u]\)這樣的值,在\(x\)的子樹中處理完之後只要提出\(bag[w[x]+d[x]]\)的答案即可,但這樣我們會發現會統計進起點根本不是\(x\)子樹中的路徑,因此我們先記錄下到\(x\)時\(bag[w[x]+d[x]]\)的值,在處理完子樹之後再將\(bag[w[x]+d[x]]\)的值和原值相減即可。

但是還有像紅色這樣的路徑會被考慮,所以在跑\(x\)的子樹中的節點(設為\(y\))時,我們將以\(y\)為\(lca\)的路徑從桶中減去即可,這樣我們統計到的答案就沒有多餘的了。

同樣,考慮\((t,lca)\)時,我們要滿足的式子為:\(w[x]-d[x]=d[u]-2*d[lca]\)即可。(注意這裡可能出現負數,我們加上\(n_\))即可。

還有一點,在計算\(x\)的答案時,不要忘了以\(x\)為路徑起點或終點時可以對上面產生貢獻,要同時更新\(bac\)中的值。

做完之後,所有路徑\(lca\)的點答案會被算兩次,要減掉

#includeusing namespace std;

#define int long long

inline int read()

while(x!=eof&&x>='0'&&x<='9')

return w*f;

}const int n=300010,m=1000010;

int n,m,num_edge,md;

int las[n][21],ans[n],boki[n];

vectorlex[n],end[n],lca[n];

int head[n],dep[n],w[n],bag[m];

struct edge edge[n<<1];

struct group ply[n];

inline void add(int from,int to)

inline void dfs(int pos,int fa)

inline int lca_ask(int u,int v)

inline void dfs_for_from(int pos,int fa)//統計路徑(s,lca)的答案

inline void dfs_for_to(int pos,int fa)//統計路徑(lca,t)的答案

main()

dfs_for_from(1,0);memset(bag,0,sizeof(bag));dfs_for_to(1,0);

for(int i=1;i<=m;i++)

if(dep[ply[i].from]-dep[ply[i].lca]==w[ply[i].lca])

ans[ply[i].lca]--;//減去路徑lca答案重複計算的部分

for(int i=1;i<=n;i++) printf("%lld ",ans[i]);

}

NOIP2016 天天愛跑步

時間限制 2 s 記憶體限制 512 mb 題目描述 小c同學認為跑步非常有趣,於是決定製作一款叫做 天天愛跑步 的遊戲。天天愛跑步 是乙個養成類遊戲,需要玩家每天按時上線,完成打卡任務。這個遊戲的地圖可以看作一棵包含n個結點和n 1條邊的樹,每條邊連線兩個結點,且任意兩個結點存在一條路徑互相可達。...

NOIP2016天天愛跑步

小c同學認為跑步非常有趣,於是決定製作一款叫做 天天愛跑步 的遊戲。天天愛跑步 是乙個養成類遊戲,需要玩家每天按時上線,完成打卡任務。這個遊戲的地圖可以看作一一棵包含 nn n個結點和 n 1n 1n 1條邊的樹,每條邊連線兩個結點,且任意兩個結點存在一條路徑互相可達。樹上結點編號為從11 1到nn...

NOIP2016 天天愛跑步

看這道題不爽很久了,但一直沒有開它,原因是我不會 我太菜了 看了題解還是寫不來,因為我不會線段樹合併。然後今天學了dsu on tree這種神奇的科技,成功把它a了,效率吊打線段樹合併。於是寫篇題解紀念一下。洛谷p1600 天天愛跑步 不帶修改的樹上路徑資訊的維護,很容易想到樹上差分。我們考慮一條路...