給定一棵樹,從時刻 0 開始,有若干人從 s[i] 出發向 t[i] 移動,每單位時刻移動一條邊
對於樹上每個點 x,求 w[x] 時刻有多少人恰好路過 x
n,m≤300000
從上午11點做到下午3點45終於做出來了。
一開始堅持自己的想法,發現錯了之後不知道怎麼改,無奈看了題解。
列出恰好路過的條件並化簡
在 si 到 lca(si,ti ) 階段,應滿足 d[si ]=w[x]+d[x]
在 lca(si,ti ) 到 ti階段,應滿足 d[si]-2∗d[lca(si,ti )]=w[x]-d[x]
相當於在 si 位置出現乙個 a 類數 d[si ],在 lca(si,ti ) 的父節點消失
在 ti 位置出現乙個 b 類數 d[si ]-2∗d[lca(si,ti )],在 lca(si,ti ) 消失
求子樹 x 中,等於 w[x]+d[x] 的 a 類數個數 + 等於 w[x]-d[x] 的 b 類數個數
全域性陣列計數,統計遍歷子樹 x 前後相應位置上的差我一開始就是沒注意這死活調不出來
1 #include2 #include3 #include4 #include5 #include6 #include7view codeusing
namespace
std;
8const
int n=300010
;9 vectorv1[n],v2[n],v3[n],v4[n];
10int
cnt,head[n];
11int fa[n][32
],dep[n];
12int book1[n],book2[n*2
];13
intn,m,w[n],ans[n];
14struct
edgee[n*2
];17
void add(int u,int
v)23
void dfs1(int u,int f,int
deep)31}
32int lca(int u,int
v)37
if(u==v)return
u;38
for(int i=30;i>=0;i--)42}
43return fa[u][0
];44}45
void dfs2(int
u)50
for(int i=0;i)
53for(int i=0;i)
56for(int i=0;i)
59for(int i=head[u];i;i=e[i].nxt)
64 ans[u]=book1[w[u]+dep[u]]+book2[w[u]-dep[u]+n]-ans[u];65}
66int
main()
74 dfs1(1,0,1
);75
for(int i=1;i<=30;i++)
76for(int j=1;j<=n;j++)
77 fa[j][i]=fa[fa[j][i-1]][i-1
];78
for(int i=1;i<=n;i++)
81for(int i=1;i<=m;i++)
90for(int i=0;i0].size();i++)
93for(int i=0;i0].size();i++)
96for(int i=0;i0].size();i++)
99for(int i=0;i0].size();i++)
102 dfs2(1
);103
for(int i=1;i<=n;i++)
106return0;
107 }
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 天天愛跑步 不帶修改的樹上路徑資訊的維護,很容易想到樹上差分。我們考慮一條路...