/*节点的标号从1开始 */ #include <cstdio> #include <algorithm> using namespace std; const int N = 10000; //N为节点的个数 struct e{ int v; e* nxt; }es[N<<1], *fir[N]; struct node{ int ls, rs; //左右儿子的下标,为-1表示空 int l, r; //区间的左右标号 //数据域,根据不同的需要添加,数据的down和update和线段树的无异 int mid() { return (l + r) >> 1; } }nodes[N<<1]; int n, en; int que[N], par[N], dep[N], root[N], seg[N], st[N], ed[N], top[N], sons[N], id[N]; //que用于BFS,par记录父节点,dep记录节点的深度。 root[i]为链i的根节点,seg用于在链上建线段树, //st[i],ed[i]分别为链i的左右端点,top[i]为链i的顶部的节点,sons[i]为节点i的儿子节点 //id[i]是节点i所属的链的标号, int ln, cnt, tr; //ln是链的个数,cnt为节点的个数,tr是树的根节点 inline void add_e(int u, int v){ es[en].v = v; es[en].nxt = fir[u]; fir[u] = &es[en++]; } inline void newNode(int& id, int l, int r){ nodes[cnt].ls = nodes[cnt].rs = -1; nodes[cnt].l = l; nodes[cnt].r = r; id = cnt++; } void build(int& id, int l, int r){ //在剖分出来的链上构建线段树 newNode(id, l, r); if(l >= r){ //seg[l]为落在这个线段树节点上的原树中的节点 return ; } int mid = (l+r)>>1; build(nodes[id].ls, l, mid); build(nodes[id].rs, mid+1, r); } void initTree(){ //初始化剖分树 //确定父亲 int l, r, u, v, i; e* cur; l = r = 0; que[r++] = tr; par[tr] = -1; dep[tr] = 0; while(l != r){ u = que[l++]; int g = 1; for(cur = fir[u]; cur; cur = cur->nxt){ if((v = cur->v) != par[u]){ que[r++] = v; par[v] = u; dep[v] = dep[u]+1; } } } //计算子树大小 for(i = 1; i <= n; i++){ sons[i] = 1; id[i] = -1; } for(i = r-1; i >= 0; i--){ u = que[i]; if(par[u] >= 0){ sons[par[u]] += sons[u]; } } //剖分链 l = r = 0; que[r++] = tr; ln = cnt = 0; while(l != r){ u = que[l++]; st[ln] = dep[u]; //用节点的深度作为线段树中区间的左右标号 top[ln] = u; while(u >= 0){ id[u] = ln; ed[ln] = dep[u]; seg[dep[u]] = u; int best; for(cur = fir[u], best=-1; cur; cur = cur->nxt){ if(id[v = cur->v] == -1){ if(best == -1 || (best >= 0 && sons[v] > sons[best])){ best = v; } } } if(best >= 0){ for(cur = fir[u]; cur; cur = cur->nxt){ if(id[v = cur->v] == -1 && best != v){ que[r++] = v; } } } u = best; } root[ln] = -1; build(root[ln], st[ln], ed[ln]); ln++; } } void lqry(int& id, int ql, int qr){ if(id == -1) return ; if(ql <= nodes[id].l && nodes[id].r <= qr){ return ; } if(nodes[id].l == nodes[id].r){ return ; } int mid = (nodes[id].l+nodes[id].r)>>1; if(ql <= mid){ lqry(nodes[id].ls, ql, qr); } if(qr > mid){ lqry(nodes[id].rs, ql, qr); } } void qry(int u, int v){ //查询u和v之间的最大值 while(id[u] != id[v]){ if(id[u] > id[v]){ swap(u, v); } int b = id[v]; lqry(root[b], st[b], dep[v]); v = par[top[b]]; } if(dep[u] > dep[v]){ swap(u, v); } lqry(root[id[u]], dep[u], dep[v]); } int main(){ return 0; }