• QTREE树剖


    题目内容:

    ————————————————————————————————————————————————————

    Time Limit: 851MS   Memory Limit: 1572864KB   64bit IO Format: %lld & %llu

     Status

    Description

    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 ab 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、读入图(边表)。
    2、第一次DFS,维护树中各个点的深度、父亲、子树大小、重儿子。
    3、第二次DFS,维护树中各个链的顶节点,和各个节点在线段树中的位置。
    4、建空线段树。
    5、依次读取各条边(因为边表每边读取2边,所以要隔一条读一条),调整U,V的次序,保证边权落在子节点上,更新子节点在线段树中的位置。
    6、读取到更新命令时,依照(5)中的方法更新,但是因为U、V的次序已经调整,则无需调整,只需要更新边2*x-1的子节点即可。
    7、读取到查询命令时,首先判断两点是否在一条链上,(a)如果不,查询深度更深的点到它所在链的链顶的最大值,然后让该点更新为链顶点的父亲,并更新链顶继续判断,直到在一条链上为止。(b)如果在一条链上则,2点是否为同一点,如果是则直接返回,否则调整U、v两点的位置,查询u在线段树中位置+1(因为U点代表U上边的边)到v的位置的最大值,更新ans,返回输出。

      1 #include<cstdio>
      2 #include<iostream>
      3 #include<cstring>
      4 
      5 using namespace std;
      6 struct edge
      7 {
      8     int u,v,w,next;
      9 }e[20010];
     10 struct node
     11 {
     12     int l,r,val;
     13     node * lc,* rc;
     14 }*root=NULL;
     15 int t,n;
     16 int head[10010],js,p;
     17 int fa[10010],son[10010],dep[10010],top[10010],siz[10010],fpos[10010],pos[10010];
     18 void init()
     19 {
     20     js=0;
     21     memset(head,0,sizeof(head));
     22     p=0;
     23     memset(e,0,sizeof(e));
     24     memset(son,0,sizeof(son));
     25 }
     26 void addage(int u,int v,int w)
     27 {
     28     e[++js].u=u;e[js].v=v;e[js].w=w;
     29     e[js].next=head[u];head[u]=js;
     30 }
     31 void dfs(int u,int f,int d)//????????????????? 
     32 {
     33     fa[u]=f;dep[u]=d;siz[u]=1;
     34     for(int i=head[u];i;i=e[i].next)
     35     {
     36         int v=e[i].v;
     37         if(v!=f)
     38         {
     39             dfs(v,u,d+1);
     40             siz[u]+=siz[v];
     41             if(!son[u]||siz[son[u]]<siz[v])
     42             son[u]=v;
     43         }
     44     }
     45 }
     46 void getpos(int u,int tp)//??top,pos(????????)
     47 {
     48     top[u]=tp;
     49     pos[u]=++p;
     50 //    fpos[pos[u]]=u;
     51     if(!son[u])return;
     52     getpos(son[u],tp);
     53     for(int i=head[u];i;i=e[i].next)
     54     {
     55         int v=e[i].v;
     56         if(v!=son[u]&&v!=fa[u])
     57             getpos(v,v);
     58     }
     59 }
     60 void build(node * &pt,int l,int r)
     61 {
     62     pt=new(node);
     63     pt->l=l;pt->r=r;pt->val=0;
     64     if(l==r)
     65     {
     66         pt->lc=pt->rc=NULL;
     67         return ;
     68     }
     69     int mid=(l+r)/2;
     70     build(pt->lc,l,mid);
     71     build(pt->rc,mid+1,r);
     72 }
     73 void update(node * p,int ps,int val)
     74 {
     75     if(p->l==p->r)
     76     {
     77         p->val=val;
     78         return ;
     79     }
     80     int mid=(p->l+p->r)/2;
     81     if(ps<=mid)update(p->lc,ps,val);
     82     else update(p->rc,ps,val);
     83     p->val=max(p->lc->val,p->rc->val);
     84 }
     85 int query(node * p,int l,int r)
     86 {
     87     if(l<=p->l&&p->r<=r)return p->val;
     88     int mid=(p->l+p->r)/2;
     89     int ans=0;
     90     if(l<=mid)ans=max(ans,query(p->lc,l,r));
     91     if(r>mid)ans=max(ans,query(p->rc,l,r));
     92     return ans;
     93 }
     94 int find(int u,int v)
     95 {
     96     int tp1=top[u],tp2=top[v],ans=0;
     97     while(tp1!=tp2)
     98     {
     99         if(dep[tp1]<dep[tp2])
    100         {
    101             swap(tp1,tp2);
    102             swap(u,v);
    103         }
    104         ans=max(ans,query(root,pos[tp1],pos[u]));
    105         u=fa[tp1];tp1=top[u];
    106     }
    107     if(u==v)return ans;
    108     if(dep[u]>dep[v])swap(u,v);
    109     return max(ans,query(root,pos[u]+1,pos[v]));
    110 }
    111 int main()
    112 {
    113     cin>>t;
    114     while(t--)
    115     {
    116         init();
    117         scanf("%d",&n);
    118         for(int i=1;i<n;i++)
    119         {
    120             int a,b,c;
    121             scanf("%d%d%d",&a,&b,&c);
    122             addage(a,b,c);
    123             addage(b,a,c);
    124         }
    125         dfs(1,0,1);
    126         getpos(1,1); 
    127         build(root,1,p);
    128         for(int i=1;i<2*n-2;i+=2)
    129         {
    130             if(dep[e[i].v]<dep[e[i].u])swap(e[i].v,e[i].u);
    131             update(root,pos[e[i].v],e[i].w);
    132 //            cout<<e[i].u<<"------"<<e[i].v<<"-----"<<endl;
    133         }
    134         char s[10];
    135         int u,v;
    136         while(scanf("%s",s)==1)
    137         {
    138             if(s[0]=='D')break;
    139             scanf("%d%d",&u,&v);
    140             if(s[0]=='Q')printf("%d\n",find(u,v));
    141             else update(root,pos[e[u*2-1].v],v);
    142         }
    143     }
    144     return 0;
    145 }
  • 相关阅读:
    C# 微信小程序模板消息---发送
    (转)python的 __init_, __call__, __new__ 详解
    (转)[Python]实例方法、类方法、静态方法
    (转)Python——gRPC详解及实战避坑方案(下)
    (转)Python——gRPC详解及实战避坑方案(上)
    (转)pika详解(五)登录认证及connectionParameters
    (转)pika详解(四) channel 通道
    (转)pika详解(三)SelectConnection及其他Connection
    (转)pika详解(二) BlockingConnection
    (转)pika详解 (一)
  • 原文地址:https://www.cnblogs.com/gryzy/p/6002627.html
Copyright © 2020-2023  润新知