• SPOJ 375 Query on a tree(树链剖分)


    https://vjudge.net/problem/SPOJ-QTREE

    题意:

    给出一棵树,树上的每一条边都有权值,现在有查询和更改操作,如果是查询,则要输出u和v之间的最大权值。

    思路:

    树链剖分的模板题。

    树链剖分简单来说,就是把树分成多条链,然后再将这些链映射到数据结构上处理(线段树,树状数组等等)。

    具体的话可以看看这个http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html

      1 #include<iostream>
      2 #include<algorithm>
      3 #include<cstring>
      4 #include<cstdio>
      5 #include<vector>
      6 #include<stack>
      7 #include<queue>
      8 #include<cmath>
      9 #include<map>
     10 #include<set>
     11 using namespace std;
     12 typedef long long ll;
     13 const int INF = 0x3f3f3f3f;
     14 const int maxn=20000+5;
     15 
     16 int n;
     17 int tot;
     18 int pos;
     19 int head[maxn];
     20 int dep[maxn];  //节点在树上的深度
     21 int top[maxn];  //节点所在重链的顶端节点
     22 int num[maxn];  //节点的子节点数
     23 int fa[maxn];   //父亲结点
     24 int p[maxn];    //节点与其父亲结点在线段树中的位置
     25 int fp[maxn];   //和p数组相反
     26 int son[maxn];  //节点的重儿子
     27 int e[maxn][3];
     28 
     29 struct node
     30 {
     31     int v,next;
     32 }edge[2*maxn];
     33 
     34 void addEdge(int u, int v)
     35 {
     36     edge[tot].v=v;
     37     edge[tot].next=head[u];
     38     head[u]=tot++;
     39 }
     40 
     41 
     42 //求出重儿子等等
     43 void dfs(int u, int pre, int d)
     44 {
     45     dep[u]=d;
     46     son[u]=-1;
     47     num[u]=1;
     48     fa[u]=pre;
     49     for(int i=head[u];i!=-1;i=edge[i].next)
     50     {
     51         int v=edge[i].v;
     52         if(v==pre)  continue;
     53         dfs(v,u,d+1);
     54         num[u]+=num[v];
     55         if(son[u]==-1 || num[son[u]]<num[v])  //找到子节点最多的作为重儿子
     56             son[u]=v;
     57     }
     58 }
     59 
     60 //处理top值以及在线段树上的位置
     61 void getpos(int u, int sp)
     62 {
     63     top[u]=sp;
     64     if(son[u]!=-1)  //先处理重儿子
     65     {
     66         p[u]=pos++;  //保证了一条链上的顶点在线段树上连续
     67         fp[p[u]]=u;
     68         getpos(son[u],sp);
     69     }
     70     else  //到了叶子节点就不再往下处理
     71     {
     72         p[u]=pos++;
     73         fp[p[u]]=u;
     74         return;
     75     }
     76     for(int i=head[u];i!=-1;i=edge[i].next) //处理其他顶点
     77     {
     78         int v=edge[i].v;
     79         if(v==son[u] || v==fa[u])  continue;
     80         getpos(v,v);
     81     }
     82 }
     83 
     84 int val[maxn<<2];
     85 int MAX[maxn<<2];
     86 
     87 
     88 void PushUp(int o)
     89 {
     90     MAX[o]=max(MAX[o<<1],MAX[o<<1|1]);
     91 }
     92 
     93 void build(int l, int r, int o)
     94 {
     95     if(l==r)
     96     {
     97         MAX[o]=val[l];
     98         return;
     99     }
    100     int mid=(l+r)>>1;
    101     build(l,mid,o<<1);
    102     build(mid+1,r,o<<1|1);
    103     PushUp(o);
    104 }
    105 
    106 void update(int pos, int x, int l, int r, int o)
    107 {
    108     if(l==r)  {MAX[o]=x;return;}
    109     int mid=(l+r)>>1;
    110     if(pos<=mid)  update(pos,x,l,mid,o<<1);
    111     else     update(pos,x,mid+1,r,o<<1|1);
    112     PushUp(o);
    113 }
    114 
    115 int query(int ql, int qr, int l, int r, int o)
    116 {
    117     if(ql<=l && qr>= r)  return MAX[o];
    118     int mid=(l+r)>>1;
    119     int res=0;
    120     if(ql<=mid)  res=max(res,query(ql,qr,l,mid,o<<1));
    121     if(qr>mid)   res=max(res,query(ql,qr,mid+1,r,o<<1|1));
    122     return res;
    123 }
    124 
    125 
    126 int lca(int x, int y)
    127 {
    128     int ans=0;
    129     while(top[x]!=top[y])  //不在一条链上时
    130     {
    131         if(dep[top[x]]<dep[top[y]])  swap(x,y);  //从深度较深的开始
    132         ans=max(ans,query(p[top[x]],p[x],1,n,1));
    133         x=fa[top[x]];  //x所在链的顶点的父节点,转到另一条链上
    134     }
    135     if(dep[x]>dep[y])  swap(x,y);
    136     if(x!=y)  ans=max(ans,query(p[son[x]],p[y],1,n,1));
    137     return ans;
    138 }
    139 
    140 
    141 int main()
    142 {
    143     //freopen("in.txt","r",stdin);
    144     int T;
    145     scanf("%d",&T);
    146     while(T--)
    147     {
    148         tot=0;
    149         memset(head,-1,sizeof(head));
    150         scanf("%d",&n);
    151         for(int i=1;i<n;i++)
    152         {
    153             scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
    154             addEdge(e[i][0],e[i][1]);
    155             addEdge(e[i][1],e[i][0]);
    156         }
    157         dfs(1,0,0);
    158         pos=1;
    159         getpos(1,1);
    160         for(int i=1;i<n;i++)
    161         {
    162             if(dep[e[i][0]]<dep[e[i][1]]) swap(e[i][0],e[i][1]);
    163             val[p[e[i][0]]]=e[i][2];
    164         }
    165         build(1,n,1);
    166         char s[10]; int u,v;
    167         while(scanf("%s",s))
    168         {
    169             if(s[0]=='D') break;
    170             scanf("%d%d",&u,&v);
    171             if(s[0]=='Q')  printf("%d
    ",lca(u,v));
    172             else  update(p[e[u][0]],v,1,n,1);
    173         }
    174     }
    175     return 0;
    176 }
  • 相关阅读:
    有关javamelody的配置
    jsp页面路径问题
    mavne问题解决---Dynamic Web Module 2.3 or newer
    centos配置数据源和java环境配置
    iBatis之Iterator的使用
    [转]Android MediaPlayer状态机
    [转]Android Activity的加载模式和onActivityResult方法之间的冲突
    ubuntu1304无法启动桌面系统的问题和解决
    java使用AES256解密
    [转]理解Linux的处理器负载均值
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7427598.html
Copyright © 2020-2023  润新知