傳送門
1a此題暴祭
(下面記點\(x\)深度為\(de_x\),某個時間點記為\(w_x\))
首先,每條路徑是可以拆成往上和往下兩條路徑的
對於往上的路徑,假設有個人往上跑,\(w_y\)在點\(y\),那麼如果能對點\(x\)的觀察員產生貢獻,當且僅當\(w_x+de_x=w_y+de_y\)
對於往下的路徑,假設有個人往下跑,\(w_y\)在點\(y\),那麼如果能對點\(x\)的觀察員產生貢獻,當且僅當\(w_x-de_x=w_y-de_y\)
所以對於每個點開兩個線段樹,每個下表存\(w_x+de_x\)或\(w_x-de_x\)的點的個數,對於每條路徑(x,y),記\(len\)為路徑長度(結束時間點),\(mid\)為到達\(lca\)的時間,在\(x\)的第乙個線段樹的\(de_x\)處+1,在\(lca\)的第乙個線段樹的\(mid+de_\)處-1,在y的第二個線段樹的\(len-de_y+n\)處+1,在\(fa_\)的第二個線段樹的\(mid-1-de_}+n\)處-1(不能出現負下標).dfs整棵樹,把\(x\)所有兒子的線段樹並起來,然後這個點的答案就是第一棵線段樹的\(w_x+de_x\)加第二棵線段樹的\(w_x-de_x+n\)的值
我太傻了,這兩顆線段樹可以分開處理的,我放在一起處理了,空間**,bzoj就過不去了qwq
#include#define ll long long
#define il inline
#define re register
#define db double
#define eps (1e-5)
using namespace std;
const int n=300000+10;
il ll rd()
while(ch>='0'&&ch<='9')
return x*w;
}int to[n<<1],nt[n<<1],hd[n],tot=1;
il void add(int x,int y)
int n,m,w[n],an[n],fa[n],sz[n],de[n],son[n],top[n];
void dfs1(int x)
else
s[o1]=s[o2]+dt;
}} int merge(int o1,int o2)
int quer(int o,int l,int r,int lx)
}s,t;
il void dfs3(int x)
an[x]=s.quer(s.rt[x],1,n+n,w[x]+de[x])+t.quer(t.rt[x],1,n+n,w[x]-de[x]+n);
}int main()
dfs3(1);
for(int i=1;i<=n;i++) printf("%d ",an[i]);
return 0;
}
luogu P1600 天天愛跑步
膜你賽t3考了這題的簡化版,當場自閉。就此把此類題目總結一下。膜你賽題意是這樣的 相當於這個題最後問每個運動員被多少個觀察員觀察到。我們考慮把每條路徑拆成向上和向下兩條,本質相同,我們以向上路徑舉例。發現路徑上滿足 dep s dep x x s 表示路徑起點 的 x 都可以獲得 1 的貢獻。我們差...
luogu P1600 天天愛跑步 LCA
luogu p1600 noip 2016 天天愛跑步 題目描述 小c同學認為跑步非常有趣,於是決定製作一款叫做 天天愛跑步 的遊戲。天天愛跑步 是乙個養成類遊戲,需要玩家每天按時上線,完成打卡任務。這個遊戲的地圖可以看作一一棵包含n個結點和n 1條邊的樹,每條邊連線兩個結點,且任意兩個結點存在一條...
洛谷 P1600 天天愛跑步
題面就不貼上了 把每個玩家的路徑拆成一條到lca的路徑和從lca到終點的路徑 然後,使用樹上差分統計答案即可 那麼,樹上差分是什麼?差分的具體思想是,當某區間內某元素對答案有貢獻,就在區間起點打乙個 1 標記代表多出了乙個對答案有貢獻的元素,在終點打乙個 1標記代表乙個對答案有貢獻的元素在該位置 結...