noip 2016 天天愛跑步

2022-04-30 07:06:07 字數 3518 閱讀 9136

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

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

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

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

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

第一行有兩個整數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的觀察員可以觀察到多少人。

6 3

2 31 2

1 44 5

4 60 2 5 1 2 3

1 51 3

2 6

copy

2 0 0 1 1 1
copy

5 3

1 22 3

2 41 5

0 1 0 3 0

3 11 4

5 5

copy

1 2 1 0 1
copy

每個測試點時限2秒。

【子任務】

【樣例1說明】

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

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

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

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

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

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

noip 2016 提高組 day 1 第二題

—————————————————————————

這道題我寫的o(n)的掃瞄線 但是預處理要nlognqaq

其實可以寫成o(n)但是有點複雜就沒寫

我們把修改(就是走來走去的玩家)拆成四個修改

就是類似差分的方法 

乙個修改從 從u開始到v結束

我們就拆成四份 在u處+ v處+ (u和v的)lca處- lca的父親處-

這樣就實現了在u和v的路徑上加的操作 畫個圖感受一下吧

其餘類似辣 一共四種情況自己畫一下就好了 

然後我們考慮乙個修改對某個點答案的影響 分兩類

第一類是從下往上經過乙個點的

觀察可知 s+dis【s】【q】(s q的距離)==w【q】(觀察的時間)

滿足上一條件那麼ans【q】就會被影響

當然因為做掃瞄線我們需要把形式轉換為只和詢問和修改有關

又 dis【s】【q】=d【s】-d【q】(d表示深度)

即s+d【s】=w【q】+d【q】

第二類為從上往下經過乙個點的情況

同理 滿足的條件為 t-d【t】【q】==w【q】

轉換為 t-d【t】=w【q】-d【q】

當然因為形式不同 所以要分開存 最後合起來就好了(開兩個桶)

這樣之後我們就找到了詢問和修改的關係了

然後我們發現對乙個點有影響的修改當且僅當修改在他的子樹內

這樣我們可以做一次dfs dfs到乙個點的時候記錄一波ans1

回溯到乙個點說明關於他的修改已經全部加上了

這個時候再記錄一波ans2 那麼這個點的答案就是ans2-ans1

這樣就實現了詢問的拆分了 這樣這個問題就解決了 **其實很短 

但是細節較多

#include#include

#include

#include

const

int m=5e5+7

;int

read()

while(c>='

0'&&c<='9')

return ans*f;

}int

n,m;

intfirst[m],cnt;

struct nodee[2*m];

void ins(int a,int b); first[a]=cnt;}

void insert(int a,int

b)int

w[m];

int dep[m],f[m][25

];void dfs(int

x) }

}int find(int x,int

y)struct pos;

std::vector

e1[m],e2[m];

int ans1[2*m],ans2[2*m],ans[m];

void pans(int

x) ans[x]+=ans1[w[x]+dep[x]];

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

}int

main());

e1[lca].push_back((pos));

e2[y].push_back((pos));

e2[fa].push_back((pos));

}pans(1);

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

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

);

return0;

}

view code

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 天天愛跑步 不帶修改的樹上路徑資訊的維護,很容易想到樹上差分。我們考慮一條路...