天天愛跑步

2022-07-20 12:42:11 字數 3115 閱讀 2436

前前後後認認真真看了三篇部落格才終於明白了大概

醉了,醉了

1.這是全域性桶的方法

//

搞不明白**要差分?

//桶用來裝該深度的點對 對應的 點的貢獻

#includeconst

int n=3e5+11

;using

namespace

std;

intn,m,cnt,head[n],w[n],fa[n];

intson[n],sz[n],dep[n],ans[n];

int num[n],top[n],bucket[n*3

];vector

v1[n],v2[n],v3[n];

struct edgeedge[n<<1

];int

read()

while(isdigit(ch))

return x*f;

}void ins(int x,int

y)void dfs1(int x,int fat)++sz[x];

}void dfs2(int x,int topx)

}int lca(int x,int y)

return dep[x]x:y;

}int dis(int x,int y)

void calc1(int

x) bucket[dep[x]+n]+=num[x];

ans[x]+=bucket[dep[x]+w[x]+n]-pre;

for(int i=0;i//

離開以x為根的子樹就沒有意義了

--bucket[dep[v1[x][i]]+n];

}void calc2(int

x)

for(int i=0;i)

++bucket[dis(x,v3[x][i])-dep[x]+n];

ans[x]+=bucket[w[x]-dep[x]+n]-pre;

for(int i=0;i)

--bucket[v2[x][i]+n];

}signed main()

for(int i=1;i<=n;i++) w[i]=read();

dfs1(

1,0);dfs2(1,1

);

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

calc1(

1);calc2(1

);

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

printf(

"%d

",ans[i]);

return0;

}

2.這是在每乙個深度建立一棵線段樹,線段樹使用動態開點

#include#include

#include

#include

#include

#include

#define mxn int(6e6+5)

using

namespace

std;

intcnt,hd[mxn],n,m,tot,_dfn,w[mxn],rt[mxn],ans[mxn],dfn[mxn],fa[mxn],size[mxn],dep[mxn],son[mxn],top[mxn];

struct

edgeedge[mxn];

struct

aa[mxn];

void add(int u, int

v)void dfs1(int u, int

ff)}

void dfs2(int u, int

tp)}

struct

nodetr[mxn];

void update(int &nod, int l, int r, int k, int

val)

if (l == r) return

;

int mid = (l + r) >> 1

;

if (k <=mid) update(tr[nod].lc, l, mid, k, val);

else update(tr[nod].rc, mid + 1

, r, k, val);

tr[nod].s = tr[tr[nod].lc].s +tr[tr[nod].rc].s;

}int query(int nod, int l,int r, int ql, int

qr)int lca(int u, int

v)

if(dep[u] < dep[v]) return

u;

else

returnv;}

intmain()

dfs1(

1,0); dfs2(1,1

);

for(int i = 1; i <= n; i++) scanf("

%d",&w[i]);

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

//dep[s]-dep[i] == w[i] up line

//dep[i] + w[i] = dep[s]

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

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

tot = 0;memset(tr,0,sizeof tr); memset(rt,0,sizeof

rt);

//dep[s] + dep[t] - 2*dep[lca] - w[i] = dep[t] - dep[i] down line

//dep[s] - 2*dep[lca] + 2 * n = w[i] - dep[i] + 2 * n

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

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

ans[i] += query(rt[ w[i] - dep[i] + 2 * n], 1, n, dfn[i], size[i] + dfn[i] -1

);

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

printf(

"%d

",ans[i]);

return0;

}

跑步愛天天

對於 50 的資料 直接模擬 對於另外10 的資料 因為地圖是一條鏈,顯然 yousiki 會消滅所有距離他為偶數條邊的祖 先。對於100 的資料 我們先把整個樹 dfs 一遍,遇到乙個點就把這個點記錄到乙個陣列後邊,即求出了樹的尤拉序,顯然如果不考慮迴圈的話,guard是在這個序列上每次往後走乙個...

天天愛跑步

一道 樹上差分 lca 桶的題 說實話,這道題放在d1t2就是非常不合理的。然而ccf就是放了,並且還是能依靠csp撈錢,你也必須交錢參加比賽。這個社會是多麼的不公啊!閒扯結束 顯然如果對每條路徑都進行一次處理,複雜度不對。考慮對路徑進行一次預處理,然後進行統一的計算答案。我們發現當一條路徑對某乙個...

天天愛跑步

終於拿下noip最難一題 看別人的題解看不懂 於是準備寫一篇更通俗易懂雜亂無章的題解 樹上差分 線段樹 桶 lca 將每條路徑在lca處切成上公升路徑和下降路徑 會發現對於x號觀察員若觀察到玩家i 則必有dep i w x depx 或dep i 2 dep lca w x depx 我們用桶標記 ...