• spoj QTREE


    传送门:Problem QTREE

    https://www.cnblogs.com/violet-acmer/p/9711441.html

    题意:

        You are given a tree (an acyclic undirected connected graph,无向无环连通图) with N nodes,
        and edges numbered 1, 2, 3...N-1.
        We will ask you to perform some instructions of the following form:
        有两个操作
        CHANGE i ti : change the cost of the i-th edge to ti(第i条边的权值变为ti)
        or
        QUERY a b : ask for the maximum edge cost on the path from node a to node b
        (查询节点a,b间路径的最大权值)

    题解:

      树链剖分模板题,看代码理解的更快;

    AC代码献上:

      1 #include<iostream>
      2 #include<cstdio>
      3 #include<cmath>
      4 #include<cstring>
      5 using namespace std;
      6 #define ls(x) ((x)<<1)
      7 #define rs(x) ((x)<<1 | 1)
      8 const int maxn=10010;
      9 
     10 //===========链式前向星===============
     11 struct Node1
     12 {
     13     int to;
     14     int next;
     15 }edge[2*maxn];
     16 int head[maxn];
     17 int cnt;
     18 void addEdge(int u,int v)
     19 {
     20     edge[cnt].to=v;
     21     edge[cnt].next=head[u];
     22     head[u]=cnt++;
     23 }
     24 //====================================
     25 //=========树链剖分用到的变量=========
     26 int fa[maxn];//fa[u] : 节点u的父节点
     27 int newId[maxn];//newId[u] : u与其父亲节点的连边在线段树中的位置
     28 int depth[maxn];//depth[u] : 节点u的深度
     29 int siz[maxn];//siz[u] : 以u为根的子树的节点数
     30 int top[maxn];//top[u] : 节点u所在的重链的顶端节点
     31 int son[maxn];//son[u] : 节点u重儿子
     32 int label;//记录newId[]中新边对应的编号
     33 //====================================
     34 //==========两次DFS()================
     35 void dfs1(int u,int f,int d) //第一遍dfs求出fa[],depth[],siz[],son[]
     36 {
     37     depth[u]=d;
     38     fa[u]=f;
     39     siz[u]=1;
     40     for(int i=head[u];~i;i=edge[i].next)
     41     {
     42         int to=edge[i].to;
     43         if(to != f)
     44         {
     45             dfs1(to,u,d+1);
     46             siz[u] += siz[to];
     47             if(son[u] == -1 || siz[to] > siz[son[u]])
     48                 son[u] = to;
     49         }
     50     }
     51 }
     52 void dfs2(int u,int sp) //第二遍dfs求出top[]和newId[]
     53 {
     54     top[u]=sp;
     55     newId[u]=++label;
     56     if(son[u] == -1)
     57         return ;
     58     dfs2(son[u],sp);
     59 
     60     for(int i=head[u];~i;i=edge[i].next)
     61     {
     62         int to=edge[i].to;
     63         if(to != son[u] && to != fa[u])
     64             dfs2(to,to);
     65     }
     66 }
     67 //===================================
     68 //=============线段树================
     69 struct Node2
     70 {
     71     int l,r;
     72     int Max;
     73     int mid()
     74     {
     75         return l+((r-l)>>1);
     76     }
     77 }segTree[maxn*4];
     78 void buildTree(int l,int r,int pos)
     79 {
     80     segTree[pos].l = l,segTree[pos].r = r;
     81     segTree[pos].Max = 0;
     82     if(l == r)
     83         return;
     84 
     85     int mid = (l+r)/2;
     86     buildTree(l,mid,ls(pos));
     87     buildTree(mid+1,r,rs(pos));
     88 }
     89 void push_up(int k)//向上更新
     90 {
     91     segTree[k].Max = max(segTree[ls(k)].Max,segTree[rs(k)].Max);
     92 }
     93 void update(int k,int val,int pos) //单点更新
     94 {
     95     if(segTree[pos].l == segTree[pos].r)
     96     {
     97         segTree[pos].Max = val;
     98         return;
     99     }
    100 
    101     int mid=segTree[pos].mid();
    102 
    103     if(k <= mid)
    104         update(k,val,ls(pos));
    105     else
    106         update(k,val,rs(pos));
    107     push_up(pos);
    108 }
    109 int query(int l,int r,int pos)//查询线段树中[l,r]的最大值
    110 {
    111     if(segTree[pos].l == l && segTree[pos].r == r)
    112         return segTree[pos].Max;
    113 
    114     int mid=segTree[pos].mid();
    115 
    116     if(r <= mid)
    117         return query(l,r,ls(pos));
    118     else if(l > mid)
    119         return query(l,r,rs(pos));
    120     else
    121         return max(query(l,mid,ls(pos)),query(mid+1,r,rs(pos)));
    122 }
    123 int Find(int u,int v)//查询u->v边的最大值
    124 {
    125     int res=0;
    126     while(top[u] != top[v])
    127     {
    128         if(depth[top[u]] > depth[top[v]])
    129         {
    130             res=max(res,query(newId[top[u]],newId[u],1));
    131             u=fa[top[u]];
    132         }
    133         else
    134         {
    135             res=max(res,query(newId[top[v]],newId[v],1));
    136             v=fa[top[v]];
    137         }
    138     }
    139     if(u == v)
    140         return res;
    141     if(depth[u] > depth[v])
    142         swap(u,v);
    143     return max(res,query(newId[son[u]],newId[v],1));
    144 }
    145 //===================================
    146 void Init()
    147 {
    148     cnt=0;
    149     memset(head,-1,sizeof(head));
    150     label=0;
    151     memset(son,-1,sizeof(son));
    152 }
    153 int e[maxn][3];
    154 int main()
    155 {
    156     int T;
    157     scanf("%d",&T);
    158     while(T--)
    159     {
    160         int n;
    161         Init();
    162         scanf("%d",&n);
    163         for(int i=1;i < n;++i)
    164         {
    165             scanf("%d%d%d",&e[i][0],&e[i][1],&e[i][2]);
    166             addEdge(e[i][0],e[i][1]);
    167             addEdge(e[i][1],e[i][0]);
    168         }
    169         dfs1(1,0,0);
    170         dfs2(1,1);
    171         buildTree(1,label,1);
    172         for(int i=1;i < n;++i)
    173         {
    174             if(depth[e[i][0]] > depth[e[i][1]])
    175                 swap(e[i][0],e[i][1]);//确保 e[i][0] 为 e[i][1]的父节点
    176             update(newId[e[i][1]],e[i][2],1);//更新e[i][1]与其父节点e[i][0]的连边在线段树中的位置
    177         }
    178         char op[10];
    179         while(scanf("%s",op) && op[0] != 'D')
    180         {
    181             int u,v;
    182             scanf("%d%d",&u,&v);
    183             if(op[0] == 'Q')
    184                 printf("%d
    ",Find(u,v));
    185             else
    186                 update(newId[e[u][1]],v,1);
    187         }
    188     }
    189 }
    View Code

    分割线:2019.5.10

    省赛倒计时2天;

    熟悉一下树链剖分,改改代码风格:

      1 #include<bits/stdc++.h>
      2 using namespace std;
      3 #define ls(x) (x<<1)
      4 #define rs(x) (x<<1|1)
      5 #define mem(a,b) memset(a,b,sizeof(a))
      6 const int maxn=1e4+50;
      7 
      8 int n;///n个节点
      9 int e[maxn][3];///节点e[i][0]与节点e[i][1]有条权值为e[i][2]的边
     10 int num;
     11 int head[maxn];
     12 struct Edge
     13 {
     14     int to;
     15     int next;
     16 }G[maxn<<1];
     17 void addEdge(int u,int v)
     18 {
     19     G[num]=Edge{v,head[u]};
     20     head[u]=num++;
     21 }
     22 int fa[maxn];///fa[u]:节点u的父节点
     23 int tid[maxn];///tid[u]:节点u在线段树中的新编号
     24 int rid[maxn];///tid[u]=cnt,rid[cnt]=u,通过线段树中的编号查找节点
     25 int dep[maxn];///节点的深度
     26 int siz[maxn];///siz[u]:以u为根的子树的节点数
     27 int son[maxn];///son[u]:节点u重儿子
     28 int top[maxn];///top[u]:节点u所在重链的顶端节点
     29 struct Seg
     30 {
     31     int l,r;
     32     int maxVal;///区间维护最大值,根据题意而定
     33     int mid(){return l+((r-l)>>1);}
     34     int len(){return r-l+1;}
     35 }seg[maxn<<2];
     36 void pushUp(int pos)
     37 {
     38     seg[pos].maxVal=max(seg[ls(pos)].maxVal,seg[rs(pos)].maxVal);
     39 }
     40 void buildSegTree(int l,int r,int pos)
     41 {
     42     seg[pos].l=l;
     43     seg[pos].r=r;
     44     seg[pos].maxVal=0;
     45     if(l == r)
     46         return ;
     47     int mid=l+((r-l)>>1);
     48     buildSegTree(l,mid,ls(pos));
     49     buildSegTree(mid+1,r,rs(pos));
     50 }
     51 void Update(int l,int val,int pos)///单点更新
     52 {
     53     if(seg[pos].l == seg[pos].r)
     54     {
     55         seg[pos].maxVal=val;
     56         return ;
     57     }
     58     int mid=seg[pos].mid();
     59     if(l <= mid)
     60         Update(l,val,ls(pos));
     61     else
     62         Update(l,val,rs(pos));
     63     pushUp(pos);
     64 }
     65 int Query(int l,int r,int pos)///区间查询
     66 {
     67     if(seg[pos].l == l && seg[pos].r == r)
     68         return seg[pos].maxVal;
     69     int mid=seg[pos].mid();
     70     if(r <= mid)
     71         return Query(l,r,ls(pos));
     72     else if(l > mid)
     73         return Query(l,r,rs(pos));
     74     else
     75         return max(Query(l,mid,ls(pos)),Query(mid+1,r,rs(pos)));
     76 }
     77 int Find(int u,int v)
     78 {
     79     int topU=top[u];
     80     int topV=top[v];
     81     int ans=0;
     82     while(topU != topV)///u,v不在一条重链上
     83     {
     84         if(dep[topU] > dep[topV])///人为规定topU的深度低
     85         {
     86             swap(topU,topV);
     87             swap(u,v);
     88         }
     89         ans=max(ans,Query(tid[topV],tid[v],1));
     90         v=fa[topV];///v来到topV的父节点所在的重链
     91         topV=top[v];
     92     }
     93     if(u == v)
     94         return ans;
     95 
     96     if(dep[u] > dep[v])
     97         swap(u,v);
     98     return max(ans,Query(tid[son[u]],tid[v],1));
     99 }
    100 void DFS1(int u,int f,int depth)///第一遍DFS求出fa,dep,siz,son
    101 {
    102     fa[u]=f;
    103     siz[u]=1;
    104     dep[u]=depth;
    105     for(int i=head[u];~i;i=G[i].next)
    106     {
    107         int v=G[i].to;
    108         if(v == f)///此处是v == f才continue,在这儿出过错
    109             continue;
    110         DFS1(v,u,depth+1);
    111         siz[u] += siz[v];
    112         if(son[u] == -1 || siz[v] > siz[son[u]])///更新重儿子
    113             son[u]=v;
    114     }
    115 }
    116 void DFS2(int u,int anc,int &k)///第二遍DFS求出tid,rid,top
    117 {
    118     top[u]=anc;
    119     tid[u]=++k;
    120     rid[k]=u;
    121     if(son[u] == -1)
    122         return ;
    123     DFS2(son[u],anc,k);
    124 
    125     for(int i=head[u];~i;i=G[i].next)
    126     {
    127         int v=G[i].to;
    128         if(v != son[u] && v != fa[u])
    129             DFS2(v,v,k);
    130     }
    131 }
    132 void Solve()
    133 {
    134     DFS1(1,0,0);
    135     int k=0;
    136     DFS2(1,1,k);
    137     buildSegTree(1,k,1);///[1,k]重新编号的节点建树
    138 
    139     for(int i=1;i < n;++i)
    140     {
    141         ///将e[i][0]与e[i][1]的边权存入儿子节点e[i][1]中
    142         if(dep[e[i][0]] > dep[e[i][1]])
    143             swap(e[i][0],e[i][1]);
    144         ///更新e[i][1]与其父节点e[i][0]的连边在线段树中的位置
    145         Update(tid[e[i][1]],e[i][2],1);
    146     }
    147     char order[10];
    148     while(~scanf("%s",order) && order[0] != 'D')
    149     {
    150         int u,v;
    151         scanf("%d%d",&u,&v);
    152         if(order[0] == 'Q')
    153             printf("%d
    ",Find(u,v));///查询节点u,v间路径的最大值
    154         else///更新第u条边的权值,变为v,第u条边的权值信息记录在了tid[e[u][1]]中
    155             Update(tid[e[u][1]],v,1);
    156     }
    157 }
    158 
    159 void Init()///初始化head,num,son
    160 {
    161     num=0;
    162     mem(head,-1);
    163     mem(son,-1);
    164 }
    165 int main()
    166 {
    167     int test;
    168     while(~scanf("%d",&test))
    169     {
    170         while(test--)
    171         {
    172             Init();///多组输入test,Init()放在while(test--)内
    173             scanf("%d",&n);
    174             for(int i=1;i < n;++i)///n-1条边
    175             {
    176                 int u,v,w;
    177                 scanf("%d%d%d",&u,&v,&w);
    178                 e[i][0]=u;
    179                 e[i][1]=v;
    180                 e[i][2]=w;
    181                 addEdge(u,v);
    182                 addEdge(v,u);
    183             }
    184             Solve();
    185         }
    186     }
    187     return 0;
    188 }
    View Code
  • 相关阅读:
    mysql安装教程zip版
    《农村基层党组织党务管理信息系统设计研究》论文笔记(二十)
    《黑河学院党务信息管理系统的设计与实现》论文笔记(十九)
    《学院党务信息系统的设计与实现》论文笔记(十八)
    《企业党务管理系统》论文笔记(十七)
    《基于B/S模式的高校党务信息管理系统的设计与实现》论文笔记(十六)
    《基于J2EE平台的党建管理系统设计与实现》论文笔记(十五)
    《基层党员管理信息系统的分析与设计》论文笔记(十四)
    《课程选修管理系统的设计与实现》论文笔记(二十)
    《高校课程管理系统的开发与设计》论文笔记(十九)
  • 原文地址:https://www.cnblogs.com/violet-acmer/p/9711454.html
Copyright © 2020-2023  润新知