• 树链剖分-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 }


  • 相关阅读:
    今天看到的一些好文语句摘录
    laravel5 怎么获取数组形式的数据
    laravel5.4将excel表格中的信息导入到数据库中
    phpmax_execution_time
    laravel 5.4 导出excel表格
    使用php函数ini_set()重新设置某个配置的设置值
    艾伟_转载:VS.NET 2010 新功能 [整理] 狼人:
    艾伟_转载:[一步一步MVC]第五回:让TagBuilder丰富你的HtmlHelper 狼人:
    艾伟_转载:.NET 4.0中数组的新增功能 狼人:
    艾伟_转载:一个简单的 Generic Factory 类 狼人:
  • 原文地址:https://www.cnblogs.com/y-m-y/p/6593917.html
Copyright © 2020-2023  润新知