BZOJ4719 Noip2016 天天愛跑步

2021-07-30 16:50:37 字數 2348 閱讀 8114

小c同學認為跑步非常有趣,於是決定製作一款叫做《天天愛跑步》的遊戲。?天天愛跑步?是乙個養成類遊戲,需要

玩家每天按時上線,完成打卡任務。這個遊戲的地圖可以看作一一棵包含 n個結點和n-1 條邊的樹, 每條邊連線兩

個結點,且任意兩個結點存在一條路徑互相可達。樹上結點編號為從1到n的連續正整數。現在有個玩家,第個玩家的

起點為si ,終點為ti  。每天打卡任務開始時,所有玩家在第0秒同時從自己的起點出發, 以每秒跑一條邊的速度,

不間斷地沿著最短路徑向著自己的終點跑去, 跑到終點後該玩家就算完成了打卡任務。 (由於地圖是一棵樹, 所以

每個人的路徑是唯一的)小c想知道遊戲的活躍度, 所以在每個結點上都放置了乙個觀察員。 在結點的觀察員會選

擇在第wj秒觀察玩家, 乙個玩家能被這個觀察員觀察到當且僅當該玩家在第wj秒也理到達了結點j  。 小c想知道

每個觀察員會觀察到多少人?注意: 我們認為乙個玩家到達自己的終點後該玩家就會結束遊戲, 他不能等待一 段時

間後再被觀察員觀察到。 即對於把結點j作為終點的玩家: 若他在第wj秒重到達終點,則在結點j的觀察員不能觀察

到該玩家;若他正好在第wj秒到達終點,則在結點的觀察員可以觀察到這個玩家。

第一行有兩個整數n和m 。其中n代表樹的結點數量, 同時也是觀察員的數量, m代表玩家的數量。

接下來n-1 行每行兩個整數u和v ,表示結點u 到結點v 有一條邊。

接下來一行n 個整數,其中第個整數為wj , 表示結點出現觀察員的時間。

接下來 m行,每行兩個整數si和ti,表示乙個玩家的起點和終點。

對於所有的資料,保證 。

1<=si,ti<=n,0<=wj<=n n<=300000

輸出1行n 個整數,第個整數表示結點的觀察員可以觀察到多少人。

6 32 3

1 2

1 4

4 5

4 6

0 2 5 1 2 3

1 5

1 3

2 6

1 2 1 0 1

對於1號點,wi=0,故只有起點為1號點的玩家才會被觀察到,所以玩家1和玩家2被觀察到,共有2人被觀察到。

對於2號點,沒有玩家在第2秒時在此結點,共0人被觀察到。

對於3號點,沒有玩家在第5秒時在此結點,共0人被觀察到。

對於4號點,玩家1被觀察到,共1人被觀察到。

對於5號點,玩家1被觀察到,共1人被觀察到。

對於6號點,玩家3被觀察到,共1人被觀察到。

當時在考場上只打了25分的暴力,太弱了……現在回來補一補吧。

我們可以按照dfs的順序來計算每個點的答案,可以發現,如果一條鏈i對當前點u有貢獻,當且僅當①起點s[i]在u的子樹中 終點t[i]在u的子樹外 而且 

deep[s[i]] - deep[u] == w[u] ②終點t[i]在u的子樹中 起點s[i]在u的子樹外 而且deep[t[i]]-deep[u] == len[i] - w[u] ③起點s[i]]和終點t[i]都在u的子樹中且lca(s[i],t[i])==u

於是我們可以記錄乙個關於深度的陣列d記錄當前有哪些鏈的端點需要考慮

這些東西都可以通過把鏈拆分成標記來解決,(pos,c)表示在pos處加上c ,c=1 或 -1

所以可以先做一次dfs求出每一對s和t的lca以及每個節點的深度

然後將每一條鏈拆成4個標記,s[i] -> (deep[s[i]],1) t[i]->(deep[t[i]]-len[i]) lca[i]->(deep[s[i]],-1) fa[lca[i]]->(deep[t[i]],-1)

再跑一次dfs就好了

然後就是有一些細節 比如w[u]==0的時候答案會被統計兩次,所以要/=2

複雜度o(nα(n)+m)

#include #include #include #include #include #include using namespace std;

typedef pairpii;

struct tag;

};const int n=600010;

int n,m,d[4*n];

int s[n],t[n],lca[n],w[n],ans[n];

int ihead[n],to[n*2],inext[2*n],cnt,f[n],fa[n],dep[n];

vectorg[n];

vectort[n];

inline int getint()

void addedge(int u,int v)

int father(int x)

void tarjan(int u)

} for (int i=0;i

BZOJ4719 Noip2016 天天愛跑步

考慮鏈上做法,發現就是把每個路徑拆成一次加入和一次刪除,然後從前往後掃,走一步所有路徑經過當前點的時間就要麼加一,要麼減一,且要麼是一直加一,要麼是一直減一,可以用兩個陣列和指標來維護整體加減 用鏈剖把乙個區間轉換成o log n 個區間,即可在樹上做 include include include...

NOIP2016 bzoj4719天天愛跑步

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

bzoj4719 Noip2016 天天愛跑步

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