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 }

 

转载于:https://www.cnblogs.com/gryzy/p/6002627.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值