NOIP2016 天天愛跑步

2021-08-03 19:49:44 字數 3121 閱讀 8786

時間限制:2 s 記憶體限制:512 mb

題目描述

小c同學認為跑步非常有趣,於是決定製作一款叫做《天天愛跑步》的遊戲。《天天愛跑步》是乙個養成類遊戲,需要玩家每天按時上線,完成打卡任務。

這個遊戲的地圖可以看作一棵包含n個結點和n-1條邊的樹,每條邊連線兩個結點,且任意兩個結點存在一條路徑互相可達。樹上結點編號為從1到n的連續正整數。

現在有m個玩家,第i個玩家的起點為si,終點為ti。每天打卡任務開始時,所有玩家在第0秒同時從自己的起點出發,以每秒跑一條邊的速度,不間斷地沿著最短路徑向著自己的終點跑去,跑到終點後該玩家就算完成了打卡任務。(由於地圖是一棵樹,所以每個人的路徑是唯一的)

小c想知道遊戲的活躍度, 所以在每個結點上都放置了乙個觀察員。 在結點的觀察員會選擇在第wj秒觀察玩家, 乙個玩家能被這個觀察員觀察到當且僅當該玩家在第wj秒也理到達了結點j 。 小c想知道每個觀察員會觀察到多少人?

注意: 我們認為乙個玩家到達自己的終點後該玩家就會結束遊戲, 他不能等待一 段時間後再被觀察員觀察到。 即對於把結點j作為終點的玩家: 若他在第wj秒重到達終點,則在結點j的觀察員不能觀察到該玩家;若他正好在第wj秒到達終點,則在結點的觀察員可以觀察到這個玩家。

輸入格式

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

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

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

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

對於所有的資料,保證1≤si,ti≤n,0≤ wj ≤n。

輸出格式

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

樣例1輸入

6 3

2 3

1 2

1 4

4 5

4 6

0 2 5 1 2 3

1 5

1 3

2 6樣例1輸出

2 0 0 1 1 1

樣例2輸入

5 3

1 2

2 3

2 4

1 5

0 1 0 3 0

3 1

1 4

5 5樣例2輸出

1 2 1 0 1

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

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

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

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

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

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

如果你的程式需要用到較大的棧空間(這通常意味著需要較深層數的遞迴),請務必仔細閱讀選手目錄下的文件running/stackpdf,以了解在最終評測時棧空間的限制與在當前工作環境下調整棧空間限制的方法。

題解:day1t2lca+差分。。。

先考慮鏈的情況:

很容易寫出式子:deep[a]-deep[x]==w[x];

通過移項:deep[x]=w[x]+deep[x]。

可以發現,右邊的式子是個定值。

那麼轉移到樹上,可以分為三種情況

①.lca==a 從上沿著一條鏈往下。

②.lca==b 從下沿著一條鏈往上

③.lca!=a && lca!=b 這種情況可以分成上面兩種,a到lca和lca到b。

a到lca:deep[a]-deep[lca]==w[lca]

lca到b:2*deep[lca]-deep[b]==w[lca]

在樹上差分就可以了。

效率:mlogn 卡一卡可以過

**:

#include

#include

#include

#include

using

namespace

std;

const

int max_n = 300001;

const

int inf = 1e6+7;

vector

add1[max_n],del1[max_n],add2[max_n],del2[max_n];

int point[max_n<<1],nxt[max_n<<1],v[max_n<<1];

int fa[max_n],top[max_n],deep[max_n],size[max_n],cnt[max_n*3];

int w[max_n],ans[max_n];

int n,m,a,b,tot;

inline

void addedge(int x,int y)

inline

void init_tree()

inline

void dfs1(int now,int f)

}inline

void dfs2(int now,int tip)

inline

void find_up(int now)

for(int i=0; ifor(int i=0; iinline

void find_down(int now)

for(int i=0; ifor(int i=0; iint main()

dfs1(1,0);

dfs2(1,1);

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

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

else

if(f==a)

else

}find_up(1);

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

w[i]+=2*max_n;

find_down(1);

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

printf("%d ",ans[i]);

return

0;

}

NOIP2016天天愛跑步

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

NOIP2016 天天愛跑步

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

NOIP2016天天愛跑步

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