树链剖分——边上权值和

Queries On Tree

Problem code: TAQTREE

Tweet

All submissions for this problem are available.

Read problems statements in Mandarin Chinese and Russian.

You are given a tree of N nodes numbered from 1 to N.
The ith edge connecting node ui and vi has a weight of wi.

Your target is to handle the queries of the following two types:

  • "1 i c" : Update the weight of ith edge with the new weight c.
    (1 represents the query type).
  • "2 u v" : Find the length of the path from node u to v. (2 represents the query type).

Input

  • The first line contains a single integer N.
  • Each of the next N - 1 lines contains three integers u v w, representing an edge
    between u and v with the weight of w.
  • The next line contains a single integer Q representing the number of queries
  • Each of the next Q lines contains three integers representing a query as described above.

Output

  • For each query of type 2, output the answer in a single line.

Constraints

All test:

  • 1i < N
  • 1u, vN; uv
  • 1w, c104

40 points:

  • 1N, Q103

60 points:

  • 1N, Q105

Example

Input: 5 1 2 2 2 3 4 4 2 3 5 4 1 3 2 5 3 1 3 1 2 5 3  Output: 8 6  

Explanation

The path from 5 to 3 is 5 -> 4 -> 2 -> 3. Initially this path has the length of 1 + 3 + 4 = 8.
After the weight of the edge connect 4 and 2 was changed to 1, the new length of the path is 1 + 1 + 4 = 6.

比较基础的树链剖分题,算边上的权值和,单边修改

1 #include<bits/stdc++.h>
  2 
  3 using namespace std;
  4 typedef long long ll;
  5 
  6 #define N 223456
  7 struct node
  8 {
  9     int v,next;
 10 }e[N<<2];
 11 int head[N],tot,top[N],fa[N],deep[N],num[N];
 12 int p[N],fp[N],son[N];
 13 int pos;
 14 
 15 void init()
 16 {
 17     tot=0;
 18     memset(head,-1,sizeof(head));
 19     pos=0;
 20     memset(son,-1,sizeof(son));
 21 }
 22 void add(int u,int v)
 23 {
 24     e[tot].v=v;
 25     e[tot].next=head[u];
 26     head[u]=tot++;
 27 }
 28 void dfs1(int u,int pre,int d)
 29 {
 30     deep[u]=d;
 31     fa[u]=pre;
 32     num[u]=1;
 33     for (int i=head[u];i!=-1;i=e[i].next)
 34     {
 35         int v=e[i].v;
 36         if (v!=pre)
 37         {
 38             dfs1(v,u,d+1);
 39             num[u]+=num[v];
 40             if (son[u]==-1||num[v]>num[son[u]]) son[u]=v;
 41         }
 42     }
 43 }
 44 void getpos(int u,int sp)
 45 {
 46     top[u]=sp;
 47     p[u]=pos++;
 48     fp[p[u]]=u;
 49     if (son[u]==-1) return;
 50     getpos(son[u],sp);
 51     for (int i=head[u];i!=-1;i=e[i].next)
 52     {
 53         int v=e[i].v;
 54         if (v!=son[u]&&v!=fa[u])
 55             getpos(v,v);
 56     }
 57 }
 58 
 59 struct nod
 60 {
 61     int l,r;
 62     ll sum;
 63 }tree[N<<4];
 64 
 65 void build(int rt,int l,int r)
 66 {
 67     tree[rt].l=l;
 68     tree[rt].r=r;
 69     tree[rt].sum=0;
 70     if (l==r) return;
 71     int mid=(l+r)/2;
 72     build(rt<<1,l,mid);
 73     build(rt<<1|1,mid+1,r);
 74 }
 75 
 76 void pushup(int rt)
 77 {
 78     tree[rt].sum=tree[rt<<1].sum+tree[rt<<1|1].sum;
 79 }
 80 void update(int rt,int k,int val)
 81 {
 82     if (tree[rt].l==k&&tree[rt].r==k)
 83     {
 84         tree[rt].sum=val;
 85         return;
 86     }
 87     int mid=(tree[rt].l+tree[rt].r)/2;
 88     if (k<=mid) update(rt<<1,k,val);
 89     else update(rt<<1|1,k,val);
 90     pushup(rt);
 91 }
 92 
 93 ll query(int rt,int l,int r)
 94 {
 95     if (tree[rt].l==l&&tree[rt].r==r) return tree[rt].sum;
 96 
 97     int mid=(tree[rt].l+tree[rt].r)/2;
 98     if (r<=mid) return query(rt<<1,l,r);
 99     else if (l>mid) return query(rt<<1|1,l,r);
100     else return query(rt<<1,l,mid)+query(rt<<1|1,mid+1,r);
101 }
102 
103 ll find(int u,int v)
104 {
105     int f1=top[u],f2=top[v];
106     ll tmp=0;
107     while (f1!=f2)
108     {
109         if (deep[f1]<deep[f2])
110         {
111             swap(f1,f2);
112             swap(u,v);
113         }
114         tmp+=query(1,p[f1],p[u]);
115         u=fa[f1];
116         f1=top[u];
117     }
118     if (u==v) return tmp;
119     if (deep[u]>deep[v]) swap(u,v);
120     return tmp+query(1,p[son[u]],p[v]);
121 }
122 
123 int x[N],y[N],z[N];
124 int main()
125 {
126     int n;
127     scanf("%d",&n);
128     init();
129     for (int i=1;i<n;i++)
130     {
131         scanf("%d%d%d",&x[i],&y[i],&z[i]);
132         add(x[i],y[i]);
133         add(y[i],x[i]);
134     }
135     dfs1(1,0,0);
136     getpos(1,1);
137     build(1,0,pos-1);
138     for (int i=1;i<n;i++)
139     {
140         if (deep[x[i]]>deep[y[i]])
141             swap(x[i],y[i]);
142         update(1,p[y[i]],z[i]);
143     }
144     int Q;
145     scanf("%d",&Q);
146     while (Q--)
147     {
148         int ty,a,b;
149         scanf("%d%d%d",&ty,&a,&b);
150         if (ty==1) update(1,p[y[a]],b);
151         else printf("%lld\n",find(a,b));
152     }
153 
154     return 0;
155 }

时间: 2024-11-05 11:18:11

树链剖分——边上权值和的相关文章

hdu 5242 树链剖分找权值最大的前k条链

http://acm.hdu.edu.cn/showproblem.php?pid=5242 Problem Description It is well known that Keima Katsuragi is The Capturing God because of his exceptional skills and experience in ''capturing'' virtual girls in gal games. He is able to play k games sim

【树链剖分】权值取反,区间最大

[题面] 有一棵n个点的树,边按照1~n-1标号,每条边拥有一个边权 现在有 m 次操作,每次操作为如下三种之一: . 1 x y:边x的权值改为y . 2 x y:将点x到点y路径上的所有边权值变成相反数 . 3 x y:查询点x到点y路径上的最大边权 第一行为两个整数n,m,表示序列长度和操作次数 接下来n-1行,每行三个数a,b,v,表示a,b之间有一条权值为v的边,按照标号1~n-1的顺序给出 接下来m行, 每行以1/2/3作为第一个数,表示操作种类.接下来两个整数,格式如题,表示一次操

BZOJ 1036 [ZJOI2008]树的统计Count (树链剖分 - 点权剖分 - 单点权修改)

题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036 树链剖分模版题,打的时候注意点就行.做这题的时候,真的傻了,单词拼错检查了一个多小时... 代码如下: 1 //树链剖分 点权修改 修改单节点 2 #include <iostream> 3 #include <cstring> 4 #include <algorithm> 5 #include <cstdio> 6 using namespa

HDU3966 Aragorn&#39;s Story(树链剖分 点权 模版题)

#include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <map> #include <set> #include <vector> #include <cstdio> using namespace std; const int N=50010; s

HDU 4729 An Easy Problem for Elfness(树链剖分边权+二分)

题意 链接:https://cn.vjudge.net/problem/HDU-4729 给你n个点,然你求两个点s和t之间的最大流.而且你有一定的钱k,可以进行两种操作 1.在任意连个点之间建立一个单位1的流,费用a 2.将原先的流扩大1个单位,费用b 思路 题目已经说了是一棵树,那么树上两点的最大流就是两点路径上的最小值.其实两种操作各一次对最大流的贡献是相等的.我们分类讨论: 如果a<=b,直接算第一种方案即可,直接给s.t连一条边,对答案的贡献是k/a. 如果a>b,分两种情况.如果k

POJ3237 Tree(树链剖分 边权)

题目大意:指定一颗树上有3个操作:询问操作,询问a点和b点之间的路径上最长的那条边的长度:取反操作,将a点和b点之间的路径权值都取相反数:变化操作,把某条边的权值变成指定的值. #include <iostream> #include <algorithm> #include <cstring> #include <cmath> #include <queue> #include <map> #include <set>

poj 2763 树链剖分(单点更新,区间求值)

http://poj.org/problem?id=2763 Description After their royal wedding, Jiajia and Wind hid away in XX Village, to enjoy their ordinary happy life. People in XX Village lived in beautiful huts. There are some pairs of huts connected by bidirectional ro

hdu3966 树链剖分(区间更新和单点求值)

http://acm.hdu.edu.cn/showproblem.php?pid=3966 Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lord of the Rings. One day Aragorn finds a lot of enemies who want to invade his kingdom. As Aragorn knows, the ene

HDU 3966Aragorn&#39;s Story(树链剖分)点权更新模板

Aragorn's Story Time Limit: 10000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Total Submission(s): 4434    Accepted Submission(s): 1212 Problem Description Our protagonist is the handsome human prince Aragorn comes from The Lor