NOIP2016 天天愛跑步 解題報告

2022-04-07 10:22:36 字數 1418 閱讀 8188

一棵 \(n\) 個節點的樹, 樹的每個節點上有乙個觀察員, 每乙個觀察員的觀察時刻為 \(time_i\),

有 \(m\) 個玩家, 每個玩家在 \(0\) 時刻時從起點 \(s_i\) 開始跑步, 每時刻經過乙個節點, 沿著最短路徑向終點 \(t_i\) 跑去.

求每個觀察員能觀察到的玩家數量.

暴力列舉每個玩家的行進路線一定是 \(o(n^2)\) 的, 不可行,

那麼考慮列舉每乙個觀察員, 求它能觀察到多少個選手.

若觀察員 \(x\) 位於 \(s_i\) 到 \(lca_i\) 的路徑上, 那麼 \(x\) 能觀察到 \(i\) 的條件為

\[time_x = dep_ - dep_x

\]轉化一下變為,

\[time_x+dep_x = dep_

\]若 \(x\) 位於 \(t_i\) 到 \(lca_i\) 的路徑上, 那麼 \(x\) 能觀察到 \(i\) 的條件為

\[time_x = dis_ - (dep_t - dep_x)

\]轉化,

\[time_x - dep_x = dis - dep_t = dep_s - 2*dep_

\]看起來樹上差分, 列舉每個點的子樹, 開個桶記錄就好了.

但有個問題, 就是之前的桶會影響當前列舉到的點.

我的做法比較蠢, 先把整棵樹按照 $dfs$ 序排成乙個序列, 並建立樹狀陣列, 然後從小到大列舉差分值, 每次把所有差分值相同的點在 $dfs$ 序列上修改, 並讓所有滿足這個值的觀察員進行查詢.

其實我們考慮一下, 當前點需要的並不是整個桶, 只需要它自己的兩個值上面的值就行了.

所以我們列舉到每個點的時候先記錄一下它的兩個值, 然後列舉完它的子樹後, 再檢視它的兩個值, 求個差就行了.#include#define pb push_back

#define sz size

using namespace std;

const int n=299998+7;

const int l=20;

int n,m,dep[n],dfn[n],en[n],cnt,tme[n],f[n][l+7],ans[n],s[n],t[n],lca[n],qes[n],poi[n];

int t1[n],t2[n],c[n];

int lst[n],nxt[2*n],to[2*n],tot;

vectorp[n];

void add(int x,int y)

void pre(int u,int fa)

en[u]=cnt;

}int lca(int x,int y)

return f[x][0];

}bool rulea(int a,int b){ return tme[a]+dep[a]>n>>m;

int x,y;

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