题目链接:http://codeforces.com/problemset/problem/342/E
树链剖分代码:
#include
#include
#include
#include
using namespace std;
#define yt eg[i].to
#define lson l,m,a[rt].ls
#define rson m+1,r,a[rt].rs
#define pb push_back
const int N=100005,inf=1000001;
int cnt,v[N],fa[N],top[N],w[N],dep[N],size[N],son[N];
//size[i]以i为根的子树节点数
//son[i] i的子树中,节点数最多的儿子节点
int dis[N],root[N],id,sz;
vector lk[N];
inline int min(int a,int b){return a size[son[x]]) son[x] = yt;
}
}
int dfs2(int x,int tp){//转成1为根的有根树 对于多个子节点先走重链 再走轻边,这样可以使重链在线段树中连续分布
top[x] = tp;//x的所在重链的顶端节点
int sz = lk[tp].size();
w[x] = sz, lk[tp].pb(x);//w[i] 表示lk数组中所在的位置 lk[ top[i] ][w[i]] = i(线段树中的位置)
if(son[x])
dfs2(son[x], tp);
for(int i = v[x]; ~i ; i = eg[i].next)
if(yt != son[x] && yt != fa[x])
dfs2(yt, yt);
}
void build(int tp,int l,int r,int rt){
a[rt].ml = a[rt].mr = inf;
if(l == r) return;
int m = (l + r)>>1;
a[rt].ls = id++, a[rt].rs = id++;
build(tp,lson),build(tp,rson);
}
void update(int p, int c, int l, int r, int rt){
if(l == r)
{
a[rt].ml = l+c;
a[rt].mr = sz-1-l+c;
return;
}
int m = (l+r)>>1;
if(p <= m) update(p, c, lson);
else update(p, c, rson);
pushup(rt);
}
int query(int L, int R, int k, int l, int r, int rt){
if(L <= l && r<= R){
if(!k) return a[rt].ml;
else return a[rt].mr;
}
int m = (l + r)>>1, ret = inf;
if(L<=m) ret = min(ret, query(L, R, k, lson));
if(R >m) ret = min(ret, query(L, R, k, rson));
return ret;
}
int main(){
int T, op, n, m, i, j, k, x, y, c, f1, f2, t, d, tp, res;
while(~scanf("%d %d", &n, &m))
{
for(i = 1;i <= n; i++) dis[i] = inf,lk[i].clear();
memset(v, -1, sizeof(v));
memset(fa, 0, sizeof(fa));
for(i = cnt = 0;i < n-1; i++)
{
scanf("%d %d", &x, &y);
add(x, y), add(y, x);
}
dep[1] = dis[1] = 0, dfs1(1);
id = cnt = 0, dfs2(1, 1);
for(i = 1;i <= n; i++)
{
sz = lk[i].size();
if(top[i] == i && sz != 1)//若i是重链起点 且i不是叶子节点 也就是有重链时
{
root[i] = id ++;
build(i, 0, sz-1, root[i]);
}
}
sz = lk[1].size();
update(0, 0, 0, sz-1, root[1]);
while(m--)
{
scanf("%d%d", &op, &x);
if(op==1)
{
for(y = x; y ;y = fa[tp])
{
tp = top[y];
sz = lk[tp].size();
if(dis[y] > dep[x] - dep[y])
{
dis[y] = dep[x] - dep[y];
if(sz > 1) update(w[y], dis[y], 0, sz-1, root[tp]);
}
else break;
}
}
else{
for(res = inf, y = x; y ; y = fa[tp]){
tp = top[y];
sz = lk[tp].size();
if(sz == 1) res = min(res, dis[y] + dep[x] - dep[y]);
else{
res=min(res,query(0,w[y],1,0,sz-1,root[tp])+w[y]-(sz-1)+dep[x]-dep[y]);
res=min(res,query(w[y],sz-1,0,0,sz-1,root[tp])-w[y]+dep[x]-dep[y]);
}
}
printf("%d\n",res);
}
}
}
return 0;
}
分块代码:
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include