zoukankan      html  css  js  c++  java
  • 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 }
  • 相关阅读:
    HDU 1269 迷宫城堡
    HDU 4771 Stealing Harry Potter's Precious
    HDU 4772 Zhuge Liang's Password
    HDU 1690 Bus System
    HDU 2112 HDU Today
    HDU 1385 Minimum Transport Cost
    HDU 1596 find the safest road
    HDU 2680 Choose the best route
    HDU 2066 一个人的旅行
    AssetBundle管理机制(下)
  • 原文地址:https://www.cnblogs.com/zyb993963526/p/7427598.html
Copyright © 2011-2022 走看看