zoukankan      html  css  js  c++  java
  • 树链剖分-SPOJ375(QTREE)

    QTREE - Query on a tree

    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 perfrom some instructions of the following form:

    • CHANGE i ti : change the cost of the i-th edge to ti
      or
    • QUERY a b : ask for the maximum edge cost on the path from node a to node b

    Input

    The first line of input contains an integer t, the number of test cases (t <= 20). t test cases follow.

    For each test case:

    • In the first line there is an integer N (N <= 10000),
    • In the next N-1 lines, the i-th line describes the i-th edge: a line with three integers a b c denotes an edge between a, b of cost c (c <= 1000000),
    • The next lines contain instructions "CHANGE i ti" or "QUERY a b",
    • The end of each test case is signified by the string "DONE".

    There is one blank line between successive tests.

    Output

    For each "QUERY" operation, write one integer representing its result.

    Example

    Input:
    1
    
    3
    1 2 1
    2 3 2
    QUERY 1 2
    CHANGE 1 3
    QUERY 1 2
    DONE
    
    Output:
    1
    3

    传送门
    一句话题意:给出一棵树,要求在树上:
      1)更新某个节点的值
      2)求两个节点间最短路径上的最大值

    模板题,数据结构解析详见代码。
      1 #include<cstring>
      2 #include<cstdio>
      3 #include<algorithm>
      4 #include<cmath>
      5 #define clr(a) memset(a,0,sizeof(a));
      6 #define foru(i,x,y) for(int i=x;i<=y;i++)
      7 using namespace std;
      8 const int N=10010;
      9 struct edge{int to,nxt;}e[N*2];
     10 int t[N],a[N][3],d[N],id[N],head[N],f[N],siz[N],son[N],top[N];
     11 //f[v]        节点v的父节点编号
     12 //id[v]        节点v的父边在线段树中的编号
     13 //siz[v]    以节点v为根的数中的节点数
     14 //son[v]    节点v的子节点中siz[]最大的节点编号 
     15 //top[v]    节点v所在重链的顶端节点编号 
     16 //d[v]        节点v的深度 
     17 int ne,cnt,n;
     18 
     19 void add(int a,int b){
     20     e[++ne]=(edge){b,head[a]};head[a]=ne;
     21 }
     22 
     23 /////////////////////////////树剖////////////////////////////////////
     24 
     25 void dfs(int k,int fa,int dep){//统计f[] siz[] son[] d[] 
     26     f[k]=fa;d[k]=dep;siz[k]=1;son[k]=0;
     27     for(int i=head[k];i;i=e[i].nxt){
     28         int v=e[i].to;
     29         if(v==fa)continue;//无向图判是否走过,易漏 
     30         dfs(v,k,dep+1);
     31         siz[k]+=siz[v];
     32         if(siz[v]>siz[son[k]])son[k]=v;
     33     }
     34 }
     35 
     36 void build(int k,int tp){
     37     id[k]=++cnt;//按序将边加入线段树 
     38     top[k]=tp; 
     39     if(son[k])build(son[k],tp);//重儿子的top[]从重链顶端继承 
     40     for(int i=head[k];i;i=e[i].nxt)
     41         if(e[i].to!=son[k]&&e[i].to!=f[k])
     42             build(e[i].to,e[i].to);//轻儿子top[]为自身 
     43 }
     44 /////////////////////////////树剖////////////////////////////////////
     45 
     46 
     47 /////////////////////////////线段树////////////////////////////////////
     48 #define mid ((L+R)>>1)
     49 #define ls (k<<1)//写位运算一定要开-Wall,否则一定要记得加括号 
     50 #define rs ls+1
     51 
     52 void update(int k,int L,int R,int p,int x){
     53     if(p>R||p<L)return;
     54     if(L==R){t[k]=x;return;}
     55     update(ls,L,mid,p,x); update(rs,mid+1,R,p,x);
     56     t[k]=max(t[ls],t[rs]);
     57 }
     58 
     59 int query(int k,int L,int R,int l,int r){
     60     if(l>R||r<L)return 0;
     61     if(l<=L&&R<=r)return t[k];
     62     return max(query(ls,L,mid,l,r),query(rs,mid+1,R,l,r));
     63 }
     64 /////////////////////////////线段树////////////////////////////////////
     65 
     66 int find(int x,int y){
     67     int ans=-1e9;
     68     while(top[x]!=top[y]){//类似LCA,每次将较低的节点上跳,并统计路径上的最大值 
     69         if(d[top[x]]<d[top[y]])swap(x,y);
     70         ans=max(ans,query(1,1,cnt,id[top[x]],id[x]));
     71         x=f[top[x]];
     72     }
     73     if(d[x]>d[y])swap(x,y);//当两点处于同一条链上的时候,进行最后一次统计 
     74     if(x!=y)ans=max(ans,query(1,1,cnt,id[x]+1,id[y]));//注意,因为id[x]为x的父边,所以若不+1,就会多统计一条边 
     75     return ans;
     76 }
     77 
     78 char ch[16];
     79 void work(){
     80     int x,y;
     81     while(scanf("%s",ch),ch[0]!='D'){
     82         scanf("%d%d",&x,&y);
     83         if(ch[0]=='C')update(1,1,cnt,id[a[x][1]],y);
     84         else printf("%d
    ",find(x,y));
     85     }
     86 }
     87 
     88 void init(){
     89     clr(a);clr(e);clr(t);clr(son);clr(siz);clr(id);clr(top);clr(head);clr(d);clr(f);
     90     ne=cnt=n=0;
     91     scanf("%d",&n);
     92     foru(i,1,n-1){
     93         scanf("%d%d%d",&a[i][0],&a[i][1],&a[i][2]);
     94         add(a[i][0],a[i][1]);add(a[i][1],a[i][0]);
     95     }
     96     dfs(1,0,1);
     97     build(1,1);
     98     foru(i,1,n-1){
     99         if(d[a[i][0]]>d[a[i][1]])swap(a[i][0],a[i][1]);
    100         update(1,1,cnt,id[a[i][1]],a[i][2]);//建树 
    101     }
    102 }
    103 
    104 int main(){
    105     int T;
    106     scanf("%d",&T);
    107     while(T--){
    108         init();
    109         work();
    110     }
    111 }


  • 相关阅读:
    感知器及其Python实现
    机器学习中的偏差和方差
    tensorflow构建CNN模型时的常用接口函数
    在O(1)时间复杂度删除链表节点
    python实现剑指offer删除链表中重复的节点
    yii2 advanced版基础部分
    Yii2 baisic版gii的使用和分页
    Yii2 表单(form)
    yii2 basic版 MVC 部分
    yii2 basic版基础部分
  • 原文地址:https://www.cnblogs.com/y-m-y/p/6593917.html
Copyright © 2011-2022 走看看