题目链接:http://codeforces.com/problemset/problem/342/E
树链剖分代码:
#include<stdio.h> #include<memory.h> #include<algorithm> #include<vector> 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<int> lk[N]; inline int min(int a,int b){return a<b?a:b;} struct node{ int opt,ml,mr,ls,rs; }a[N<<2]; struct edge{ int to,next; }eg[N<<1]; void add(int x,int y){ eg[cnt].to=y; eg[cnt].next=v[x]; v[x]=cnt++; } int pushup(int rt){ int ls=a[rt].ls,rs=a[rt].rs; a[rt].ml=min(a[ls].ml,a[rs].ml); a[rt].mr=min(a[ls].mr,a[rs].mr); } int dfs1(int x){//得到重链 son[x]=0, size[x]=1; for(int i=v[x];i!=-1;i=eg[i].next){ if(yt==fa[x]) continue; fa[yt] = x; dep[yt] = dep[x]+1; dfs1(yt); size[x] += size[yt]; if(size[yt] > 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<cstdio> #include<cstring> #include<cmath> #include<ctime> #include<cstdlib> #include<cassert> #include<algorithm> #include<iostream> #include<string> #include<deque> #include<vector> #include<queue> #include<list> #include<stack> #include<set> #include<map> #include<bitset> #pragma comment(linker, "/STACK:1024000000,1024000000") using namespace std; typedef long long ll; typedef pair<int,int> pii; const int N=(int)1e5+10; vector<int>G[N],black,white; int dep[N],dp[N]; const int Pow = 18; int par[N][Pow]; void dfs(int u,int pre){ dep[u] = dep[pre] + 1; par[u][0] = pre; for(int i=1;i<Pow;i++)par[u][i] = par[par[u][i-1]][i-1]; for(int i=0;i<G[u].size();i++){ int v = G[u][i]; if(v == pre)continue; dfs(v,u); } } int LCA(int a,int b){ if(dep[a] > dep[b])swap(a,b); if(dep[a] < dep[b]){ int del = dep[b] - dep[a]; for(int i=0;i<Pow;i++) if(del&(1<<i))b = par[b][i]; } if(a!=b){ for(int i=Pow-1;i>=0;i--) if(par[a][i] != par[b][i]) a = par[a][i],b = par[b][i]; a = par[a][0],b = par[b][0]; } return a; } void bfs(){ queue<int>Q; for(int i=0;i<black.size();i++){ Q.push(black[i]);dp[black[i]] = 0; } while(!Q.empty()){ int u = Q.front();Q.pop(); for(int i=0;i<G[u].size();i++){ int v =G[u][i]; if(dp[v] > dp[u] + 1){ dp[v] = dp[u] + 1; Q.push(v); } } } black.clear(); } int main(){ int n,m; while(~scanf("%d%d",&n,&m)){ for(int i=1;i<=n;i++)G[i].clear(); for(int i=1;i<=n;i++)dp[i] = ~0u>>2; black.clear();black.push_back(1); for(int i=1;i<n;i++){ int u,v;scanf("%d%d",&u,&v); G[u].push_back(v); G[v].push_back(u); } dfs(1,0); bfs();int maxn = sqrt(m*1.0) + 1; for(int i=0;i<m;i++){ int op,u; scanf("%d%d",&op,&u); if(op==1){ black.push_back(u); if(black.size() == maxn){ bfs(); } }else{ int sz = black.size(); int ans = dp[u]; for(int i=0;i<sz;i++){ int v = black[i]; ans = min(ans,dep[u] + dep[v] - 2*dep[LCA(u,v)]); } printf("%d\n",ans); } } } return 0; }