NOIP2016天天愛跑步

2022-04-29 20:57:10 字數 4271 閱讀 2787

時間限制: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的觀察員可以觀察到多少人。

6 3

2 31 2

1 44 5

4 60 2 5 1 2 3

1 51 3

2 6

2 0 0 1 1 1
5 3

1 22 3

2 41 5

0 1 0 3 0

3 11 4

5 5

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人被觀察到。

感覺這是一道好難的題,,別人花10分鐘打dfs拿了暴力25分,我花了快乙個小時打樹鏈刨分維護線段樹也才拿了25分嗚嗚嗚~~~~(>_

上網搜別人的題解發現都講得懵懵懂懂的,反正自己是理解了好半天的呢!

我答的應該還是一些比較容易懂的方法吧..

解題報告::

發現資料n,m都是30w以上的,果斷確定演算法o(nlogn) ,而且只能選擇乙個,要麼處理人,要麼處理觀察員,我們在這裡用一下經典思路:兩個節點s,t之間的距離,可以把它看成從s到lca(最近公共祖先),從lca再到t的過程,對這兩部分過程進行分段處理就好了。

①:從s到lca的過程中,乙個觀察員i如果能夠觀察到跑步人x的話,那一定滿足式子dp[x]-dp[i]==w[i](dp是深度,w是時間,因為根節點的深度為0,並且每一條邊的長度都為一,所以dp陣列也可以看成是到根節點的距離),我們對他進行一下移項處理:dp[x]=dp[i]+w[i],可以發現等式的右邊是乙個定值,所以這時候就比較容易想到了,我們對跑步的人進行處理,詢問時查詢每乙個節點的dp[i]+w[i]即可。首先用樹鏈剖分預處理出dp陣列,求出每個人起點和終點的lca;然後進行動態插點,因為詢問時,如果觀察員能觀察到這個人,那麼dp[i]+w[i]一定等於dp[x],並且觀察到同乙個人的所有觀察員肯定滿足dp[i]+w[i]==dp[j]+w[j];所以我們對每乙個深度dp[s]進行插入,如何解決記憶體的問題呢??用線段樹的動態開點就好了,

②:返回來同理:dp[i]+dp[s]-2*dp[lca]=w[i],進行移項處理:dp[s]-2*dp[lca]==w[i]-dp[i];原理同上,但因為是減法,會出負數,所以整體右移,這就會使記憶體很大很大,開陣列的時候一定要注意,我在這裡跪了幾次(⊙o⊙)…,在處理完第乙個時候,用乙個陣列儲存答案,然後先前的那些就沒有用了,反而會對後面的產生干擾,所以在求第二次的時候,不要忘記清空線段樹,還有個細節要注意,因為lca是只經過一次的,但是你兩個路徑中卻都有,所以你要舍乙個,用fa[lca]來當上界了。

補充:因為乙個觀察員能觀察到人當且僅當這個人的路線是經過觀察員的,所以插入的時候要用到差分和dfs序的思想,乙個點在進入時有乙個時間戳,出來是有乙個時間戳,那麼在插入操作時,以第一段為例,只要在起點的時間戳出+1,再其fa[lca]處-1(包含lca),這樣如果這個人是經過觀察員的,那麼觀察員進出的時間戳中就構成了乙個連續的區間,這個區間中一定會有起點的那個+1,沒有lca的-1,如果沒有經過,要麼是區間中不含+1,或者是+1與-1抵消了,這樣都不會產生任何影響的;、

所以最後對每個節點的觀察員來說,答案即為在dp[i]+w[i]詢問其子樹中的數量+第二次w[i]-dp[i]+2*n(為了防止出負數,整體右移了2*n,陣列也要相應的擴大更多)詢問其子樹中的數量之和

輸出答案即可

總結:這道題真的好難想啊,樹鏈剖分求lca+樹上差分+動態開點線段樹+最最難想到的那個式子

╮(╯▽╰)╭貌似這道題可用dp和dfs兩種方法水過??(這個方法才叫水吧)。

附碼:

1 #include2 #include3 #include4 #include5

using

namespace

std;

6int

n,m,num,x,y,dex;

7int w[300000],adj[300000];8

int rt[7000000],lc[7000000],rc[7000000];9

struct

edgek[600000

];12

struct

stal[300000

];15

intread()

19return

sum;20}

21void init(int s,int

t)27

int fa[300000],dp[300000],son[300000],size[300000

];28

void dfs1(int

x)39}40

}41int pos[300000],id[300000],top[300000],qiong[300000

],cnt;

42void dfs2(int u,int

tp)51 qiong[u]=cnt;52}

53int lca(int x,int

y)60 x=fa[fx];fx=top[x];61}

62return dp[x]x:y;63}

64int sum[7700000

];65

void change(int x,int z,int l,int r,int &now)

74int query(int s,int t,int l,int r,int

rt)83

void

clear()

90int ans[300000

];91

intmain()

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

101 w[i]=read();

102 dfs1(1);dfs2(1,1

);103

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

104 l[i].s=read(),l[i].t=read(),l[i].lca=lca(l[i].s,l[i].t);

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

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

111 ans[i]=query(id[i],qiong[i],1,n,rt[dp[i]+w[i]]);

112clear();

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

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

119 ans[i]+=query(id[i],qiong[i],1,n,rt[w[i]-dp[i]+2*n]);

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

121 printf("

%d "

,ans[i]);

122return0;

123 }

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