标签:ble 线段 names 树链剖分 max std dfs [1] har
题目链接:http://www.spoj.com/problems/QTREE/
参考博客:http://blog.sina.com.cn/s/blog_7a1746820100wp67.html
树链剖分入门题
代码如下(附注解):
1 #include <cstdio> 2 #include <cstring> 3 #include <iostream> 4 #define lson (x<<1) 5 #define rson ((x<<1)|1) 6 #define mid ((l+r)>>1) 7 #define N 10010 8 using namespace std; 9 struct Edge{ 10 int to,next; 11 }e[N<<1]; 12 int T,n,tot,oo,root; 13 int head[N],a[N][3],tree[N<<2];//头结点,inpotData,线段树 14 int fa[N],siz[N],dep[N],son[N];//父亲,包含该节点的子树的结点数,深度,重链上的儿子 15 int top[N],p[N];//当前节点所在重链的顶端结点,当前节点与其父亲的连边在线段树中的位置 16 char s[10]; 17 void addEdge(int u,int v){//用头接法链表存当前节点的各个儿子 18 e[++oo].to=v; 19 e[oo].next=head[u]; 20 head[u]=oo; 21 } 22 void fristDFS(int v){//第一次dfs求siz,son,dep,fa 23 siz[v]=1,son[v]=0; 24 for(int i=head[v];i!=0;i=e[i].next){ 25 int u=e[i].to; 26 if(u!=fa[v]){ 27 fa[u]=v; 28 dep[u]=dep[v]+1; 29 fristDFS(u); 30 if(siz[u]>siz[son[v]])son[v]=u; 31 siz[v]+=siz[u]; 32 } 33 } 34 } 35 void secondDFS(int v,int tp){//第二次dfs求top,p 36 p[v]=++tot,top[v]=tp; 37 if(son[v]!=0)secondDFS(son[v],top[v]); 38 for(int i=head[v];i!=0;i=e[i].next){ 39 int u=e[i].to; 40 if(u!=fa[v]&&u!=son[v])secondDFS(u,u); 41 } 42 } 43 void push_up(int x){ 44 tree[x]=max(tree[lson],tree[rson]); 45 } 46 void updata(int x,int l,int r,int p,int v){//建线段树 47 if(l==r){ 48 tree[x]=v; 49 return; 50 } 51 if(p<=mid)updata(lson,l,mid,p,v); 52 else updata(rson,mid+1,r,p,v); 53 push_up(x); 54 } 55 void init(){ 56 memset(siz,0,sizeof(siz)); 57 memset(head,0,sizeof(head)); 58 scanf("%d",&n); 59 root=(n+1)/2;//任意取一个root 60 oo=tot=fa[root]=dep[root]=0; 61 for(int i=1;i<n;++i){ 62 for(int j=0;j<3;++j)scanf("%d",&a[i][j]); 63 addEdge(a[i][0],a[i][1]); 64 addEdge(a[i][1],a[i][0]); 65 } 66 fristDFS(root); 67 secondDFS(root,root); 68 for(int i=1;i<n;++i){ 69 if(dep[a[i][0]]>dep[a[i][1]])swap(a[i][0],a[i][1]); 70 //将远离root的结点放在d[i][1] 71 updata(1,1,tot,p[a[i][1]],a[i][2]); 72 } 73 } 74 int query(int x,int l,int r,int a,int b){ 75 if(a<=l&&r<=b)return tree[x]; 76 int tmp=0; 77 if(a<=mid)tmp=max(tmp,query(lson,l,mid,a,b)); 78 if(b>mid)tmp=max(tmp,query(rson,mid+1,r,a,b)); 79 return tmp; 80 } 81 int find(int x,int y){ 82 int f1=top[x],f2=top[y],tmp=0; 83 while(f1!=f2){//若x,y不在同一条重链上 84 if(dep[f1]<dep[f2])swap(f1,f2),swap(x,y); 85 //取深度大的点,f1为该重边的顶端结点,va为该结点 86 //在线段树中[f1,va]一定为一个连续的区间 87 tmp=max(tmp,query(1,1,tot,p[f1],p[x])); 88 x=fa[f1];f1=top[x]; 89 } 90 if(x==y)return tmp; 91 if(dep[y]<dep[x])swap(x,y); 92 return max(tmp,query(1,1,tot,p[son[x]],p[y]));//不包含x与其父亲构成的边 93 } 94 void solve(){ 95 int x,y; 96 for(scanf("%s",s);s[0]!=‘D‘;scanf("%s",s)){ 97 scanf("%d%d",&x,&y); 98 if(s[0]==‘Q‘)printf("%d\n",find(x,y)); 99 else if(s[0]==‘C‘)updata(1,1,tot,p[a[x][1]],y); 100 } 101 } 102 int main(void){ 103 for(scanf("%d",&T);T;T--){ 104 init(); 105 solve(); 106 } 107 }
标签:ble 线段 names 树链剖分 max std dfs [1] har
原文地址:http://www.cnblogs.com/barrier/p/6067964.html