BZOJ 4719 天天愛跑步 LCA 差分

2022-05-15 19:06:39 字數 2549 閱讀 6012

time limit: 40 sec  memory limit: 512 mb

submit: 1464  solved: 490

[submit][status][discuss]

小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

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

6 32 3

1 21 4

4 54 6

0 2 5 1 2 3

1 51 3

2 62 0 0 1 1 1

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

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

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

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

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

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

剛開始學oi的時候就看過這道題。。。當時是貼**過的。。。。

記得好像是用樹鏈剖分。。不記得了。。反正很長。。。

現在快要noip了。。。把往年的題目拿出來看一下,算是臨近noip的梳理吧。。。。。

好多廢話

進入正題。。。。。

首先每個人都要走最短路徑。。。馬上想到lca。。。不然還能有什麼。。。

每個人分別統計顯然是不行的,不過似乎可以根據特殊情況水很多分。。

於是想到差分。。

假設第 i 個人的起點為 si ,終點為 ti 。。lca ( si ,ti ) =  rt  

每條線段長度都是 1 ,故路徑長度與深度有關。。。

於是路徑就可以分成兩部分:si -> rt  和 rt ->ti

兩條路徑分開統計。。。

在向上的路徑中,比如乙個起點 si ,深度為 dep [ si ] ,

那麼可以在遍歷到si的時候 u [ dep [ si ] ] ++;

然後在到達 rt 的父親的時候 u [ dep [ si ] ] --;  (u [ i ]表示某一方向路徑的總值)

向下的路徑用一樣的方法。。。但這樣rt 的統計會有重複。。

所以兩次統計中要有一次在 rt 的時候就 u [ dep [ si ] ] - - ;

這樣就可以了,雖然分析很長但**不是很長。。。。

注意在bzoj上提交不能有末尾空格。。。害我pe了一發。。。

#include#include#include#include#include#define n 400000

using namespace std;

inline int read()

while(ch>='0'&&ch<='9')

return x*f;

}int n,m,cnt=0;

int fa[n][22];

int hed[n],w[n],dep[n],ans[n],u[n],d[n<<1];

struct edgee[n<<1];

struct node;

vectore1[n],e2[n<<1];

void insert(int u,int v);hed[u]=cnt;

e[++cnt]=(edge);hed[v]=cnt;

}void dfs1(int x,int f)

return fa[u][0];

}void dfs2(int x,int f){

ans[x]-=u[w[x]+dep[x]];

ans[x]-=d[w[x]-dep[x]+n];

for(int i=0;ithis passage is made by iscream-2001.

4719 Noip2016 天天愛跑步

time limit 40 sec memory limit 512 mb submit 1986 solved 752 submit status discuss 小c同學認為跑步非常有趣,於是決定製作一款叫做 天天愛跑步 的遊戲。天天愛跑步?是乙個養成類遊戲,需要 玩家每天按時上線,完成打卡任務...

BZOJ4719 Noip2016 天天愛跑步

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

BZOJ4719 Noip2016 天天愛跑步

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