1. 程式人生 > >[Luogu P1600] [BZOJ 4719] [NOIP 2016 tg]天天愛跑步

[Luogu P1600] [BZOJ 4719] [NOIP 2016 tg]天天愛跑步

洛谷傳送門

題目描述

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

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

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

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

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

輸入輸出格式

輸入格式:

第一行有兩個整數n

nmm 。其中nn代表樹的結點數量, 同時也是觀察員的數量, mm代表玩家的數量。

接下來 n1n- 1行每行兩個整數uuvv,表示結點 uu到結點 vv有一條邊。

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

接下來 mm 行,每行兩個整數SiS_i,和TiT_i,表示一個玩家的起點和終點。

對於所有的資料,保證1Si,Tin,0Wjn1\leq S_i,T_i\leq n, 0\leq W_j\leq n

輸出格式:

輸出11nn個整數,第j

j個整數表示結點jj的觀察員可以觀察到多少人。

輸入輸出樣例

輸入樣例#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說明】

對於11號點,Wi=0W_i=0,故只有起點為11號點的玩家才會被觀察到,所以玩家11和玩家22被觀察到,共有22人被觀察到。

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

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

對於44號點,玩家11被觀察到,共11人被觀察到。

對於55號點,玩家11被觀察到,共11人被觀察到。

對於66號點,玩家33被觀察到,共11人被觀察到。

【子任務】

每個測試點的資料規模及特點如下表所示。 提示: 資料範圍的個位上的數字可以幫助判斷是哪一種資料型別。

img

解題分析

其實 uu11vv11的部分分是在給我們提示:一條uvu\to v的路徑上可以分成兩部分: ulca(u,v),lca(u,v)vu\to lca(u, v),\ \ lca(u,v)\to v

前半部分情況路徑上的點xx可以獲得11的貢獻當且僅當dep[x]+W[x]=dep[u]dep[x]+W[x]=dep[u], 而dep[x]+W[x]dep[x]+W[x]是一個定值, 我們DFSDFS的時候記錄一下子樹中符合要求的點的個數就好了。

後半部分情況路徑上的點xx可以獲得11的貢獻當且僅當dep[x]+dep[u]2dep[lca(u,v)]=W[x]dep[x]+dep[u]-2*dep[lca(u,v)]=W[x], 而W[x]dep[x]W[x]-dep[x]是一個定值, 同樣我們記錄一下就好了。 注意這個值可能是負數, 所以記錄的時候統一+300000+300000

然而還可能出現這個路徑並不過xx的情況, 所以我們分別在uuvv打上+1+1的標記, 在兩種情況的fat[lca(u,v)]fat[lca(u,v)]打上上1-1的標記, DFSDFS到的時候記錄一下上面的滿足要求的個數, 最後子樹DFSDFS完成的時候作差即可。

有兩種特殊情況:

  1. lca(u,v)=ulca(u,v)=ulca(u,v)=vlca(u,v)=v, 這時我們只取上面的一種情況即可。
  2. dep[lca(u,v)]+W[lca(u,v)]=dep[u]dep[lca(u,v)]+W[lca(u,v)]=dep[u], 這時我們相當於多算了一次這條路徑的貢獻, 1-1即可。

程式碼如下:

#include <cstdio>
#include <cstring>
#include <cctype>
#include <algorithm>
#include <cstdlib>
#include <vector>
#define R register
#define IN inline
#define W while
#define gc getchar()
#define MX 600500
template <class T>
IN void in(T &x)
{
	x = 0; R char c = gc;
	for (; !isdigit(c); c = gc);
	for (;  isdigit(c); c = gc)
	x = (x << 1) + (x << 3) + c - 48;
}
int dep[MX], fat[MX], son[MX], siz[MX], head[MX], topf[MX];
int from[MX], to[MX], lca[MX], tim[MX], ans[MX], cntup[MX], cntdown[MX];
int dot, line, cnt;
struct Edge {int to, nex;} edge[MX << 1];
struct INFO {int tar, val;};
std::vector<INFO> up[MX], down[MX];
IN void add(R int fr, R int to) {edge[++cnt] = {to, head[fr]}, head[fr] = cnt;}
void DFS(R int now)
{
	siz[now] = 1;
	for (R int i = head[now]; i; i = edge[i].nex)
	{
		if(edge[i].to == fat[now]) continue;
		fat[edge[i].to] = now;
		dep[edge[i].to] = dep[now] + 1;
		DFS(edge[i].to);
		siz[now] += siz[edge[i].to];
		if(siz[edge[i].to] > siz[son[now]]) son[now] = edge[i].to;
	}
}
void DFS(R int now, R int grand)
{
	topf[now] = grand;
	if(!son[now]) return;
	DFS(son[now], grand);
	for (R int i = head[now]; i; i = edge[i].nex)
	{
		if(edge[i].to == fat[now] || edge[i].to == son[now]) continue;
		DFS(edge[i].to, edge[i].to);
	}
}
IN int get(R int x, R int y)
{
	W (topf[x] != topf[y])
	{
		if(dep[topf[x]] < dep[topf[y]]) std::swap(x, y);
		x = fat[topf[x]];
	}
	return dep[x] < dep[y] ? x : y;
}
void calc(R int now, R int u, R int d)
{
	for (R int i = up[now
            
           

相關推薦

[Luogu P1600] [BZOJ 4719] [NOIP 2016 tg]天天跑步

洛谷傳送門 題目描述 小c同學認為跑步非常有趣,於是決定製作一款叫做《天天愛跑步》的遊戲。《天天愛跑步》是一個養成類遊戲,需要玩家每天按時上線,完成打卡任務。 這個遊戲的地圖可以看作一一棵包含 nnn個結點和 n−1n-1n−1條邊的樹, 每條邊連線兩個結點,

Noip 2016 天天跑步 題解

最短路 oid 數量 mes stream 編號 個人 str fin     [NOIP2016]天天愛跑步           時間限制:2 s 內存限制:512 MB 【題目描述】 小C同學認為跑步非常有趣,於是決定制作一款叫做《天天愛跑步》的遊戲。《天天愛跑

[luogu]P1600 天天跑步[LCA]

== 同學 問題 i++ mil com get new sin [luogu]P1600 [NOIP 2016]天天愛跑步 題目描述 小c同學認為跑步非常有趣,於是決定制作一款叫做《天天愛跑步》的遊戲。«天天愛跑步»是一個養成類遊戲,需要玩家

NOIP 2016 天天跑步

分享圖片 size image img spa noip 必須 沒有 mil 我獨立想只想出來了前80分的做法,不過貌似我的做法離正解比較遠 測試點1~2 直接看每個點有多少玩家且這個點時間為0即可 測試點3~4 看每個點有多少個起點 測試

luogu P1600 天天跑步

void gist math str show getch 設有 wap print 傳送門 1A此題暴祭 (下面記點\(x\)深度為\(de_x\),某個時間點記為\(w_x\)) 首先,每條路徑是可以拆成往上和往下兩條路徑的 對於往上的路徑,假設有個人往上跑,\(w_y

[Luogu P5024] [BZOJ 5466] [NOIp 2018tg]保衛王國

洛谷傳送門 BZOJ傳送門 題目描述 Z Z Z 國有

bzoj 4719: [Noip2016]天天跑步 線段樹合併

題意 有一棵n個節點的樹,每條邊權為1,每個節點都會在某一個時間出現觀察員且只會出現一次。現有m個玩家,給定每個玩家的起點,然後每個玩家會在時刻0從起點出發,沿著唯一的路徑走向終點。問每個觀察員分別可以看到多少個玩家。 n,m<=300000 分析

[Luogu] 天天跑步

sin clu clas mem onclick AS work tchar ide https://www.luogu.org/problemnew/show/P1600 亂寫的暴力,這道題暴力寫個60還是比較簡單的 #include <iostream

洛谷P1600 天天跑步——樹上差分

iostream pac Go spa CM int val stream OS 題目:https://www.luogu.org/problemnew/show/P1600 看博客:https://blog.csdn.net/clove_unique/article/de

P1600 天天跑步

deb sin prior bool tin find deep tdi %d lca真心不太會,這裏只介紹60分做法,100的太難辣簡單了就不介紹了 n<=1000 zz回溯爆搜 S[i]全部相等 這dfs序都不用lca的,2333,差分,然後輸出判斷一下是否是0(

[洛谷P1600] 天天跑步

數據規模 truct 們的 路徑和 整合 bool last err 遊戲 洛谷題目鏈接:天天愛跑步 題目描述 小c同學認為跑步非常有趣,於是決定制作一款叫做《天天愛跑步》的遊戲。《天天愛跑步》是一個養成類遊戲,需要玩家每天按時上線,完成打卡任務。 這個遊戲的地圖可以看作一

4719: [Noip2016]天天跑步

Time Limit: 40 Sec Memory Limit: 512 MB Submit: 1986 Solved: 752 [Submit][Status][Discuss] Description 小c同學認為跑步非常有趣,於是決定製作一款叫做《天天愛跑步》的遊戲。?天天愛跑步?是一個養成類遊戲,

洛谷P1600 天天跑步(差分 LCA 桶)

題意 題目連結 Sol 一步一步的來考慮 \(25 \%\):直接\(O(nm)\)的暴力 鏈的情況:維護兩個差分陣列,分別表示從左向右和從右向左的貢獻, \(S_i = 1\):統計每個點的子樹內有多少起點即可 \(T_i = 1\):同樣還是差分的思想,由於每個點 能對其產生的點的深度是相同

2018.11.09【NOIP2016】【洛谷P1600天天跑步(樹上差分)

傳送門 解析: 據說這是NOIP歷年最難一道題。。但是真的沒有寶藏難啊我覺得。。。 思路: 答案分兩類統計,一種是子樹中過來,一種是其他地方過來。那麼路徑就被拆分成兩部分了,一部分是S−&gt;lcaS-&gt;lcaS−>lca,一部分

洛谷P1600 天天跑步(NOIp2016)(BZOJ4719)

LCA 炒雞難的一題。。。碼量還不小。。。 只想到拆成鏈,然而不知道怎麼實現。。。只好認慫去看題解。。。 考慮每條路徑,拆成兩個鏈。一個從s到LCA,另一個從LCA到t。如果LCA有貢獻的話就把答案-1(不然就算重啦)。 然後在每個s打個1,在L

【NOIP2016】天天跑步

truct ios 多少 個人 img 自己 ret 一行 速度 題目描述 小c同學認為跑步非常有趣,於是決定制作一款叫做《天天愛跑步》的遊戲。?天天愛跑步?是一個養成類遊戲,需要玩家每天按時上線,完成打卡任務。 這個遊戲的地圖可以看作一一棵包含 個結點和 條邊的樹, 每條

LCA+線段樹 NOIP2016 天天跑步

art swa 單獨 編譯 如果 建立 const 會有 void 天天愛跑步 題目描述 小c同學認為跑步非常有趣,於是決定制作一款叫做《天天愛跑步》的遊戲。?天天愛跑步?是一個養成類遊戲,需要玩家每天按時上線,完成打卡任務。 這個遊戲的地圖可以看作一一棵包含 nnn個結

noip2016 天天跑步

ini node 右移 += upd 時間 個人 方法 最短路 分析:這道題真心煩啊,是我做過noip真題中難度最高的一道了,到今天為止才把noip2016的坑給填滿.暴力的話前60分應該是可以拿滿的,後40分還是很有難度的. 定義:每個人的起點、終點:s,t;深度

【LCA+樹上差分】天天跑步

blog 分支 div fin out 答案 簡單 printf 但是 困擾我半年多的題終於做出來了 一開始我的做法是想在回溯的時候統計答案,但是各個分支之間又會相互影響,然後就不會做了 看完別人的題解後發現用桶的前後狀態做差來統計答案更簡單 1 #include &l

[NOIp2016提高組]天天跑步

秒拍 tin reg git clu getchar() tdi gist lin 題目大意:   有一棵n個點的樹,每個點上有一個攝像頭會在第w[i]秒拍照。   有m個人再樹上跑,第i個人沿著s[i]到t[i]的路徑跑,每秒鐘跑一條邊。   跑到t[i]的下一秒