前前後後認認真真看了三篇部落格才終於明白了大概
醉了,醉了
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 我們用桶標記 ...