Time Limit: 2 second(s) | Memory Limit: 32 MB |
Finally the Great Magical Lamp was in Aladdin's hand. Now he wanted to return home. But he didn't want to take any help from the Genie because he thought that it might be another adventure for him. All he remembered was the paths he had taken to reach there. But since he took the lamp, all the genies in the cave became angry and they were planning to attack. As Aladdin was not afraid, he wondered how many genies were there. He summoned the Genie from the lamp and asked this.
Now you are given a similar problem. For simplicity assume that, you are given a tree (a connected graph with no cycles) with n nodes, nodes represent places, edges represent roads. In each node, initially there are an arbitrary number of genies. But the numbers of genies change in time. So, you are given a tree, the number of genies in each node and several queries of two types. They are:
1) 0 i j, it means that you have to find the total number of genies in the nodes that occur in path from node i to j (0 ≤ i, j < n).
2) 1 i v, it means that number of genies in node i is changed to v (0 ≤ i < n, 0 ≤ v ≤ 1000).
Input
Input starts with an integer T (≤ 10), denoting the number of test cases.
Each case starts with a blank line. Next line contains an integer n (2 ≤ n ≤ 30000). The next line contains n space separated integers between 0 and 1000, denoting the number of genies in the nodes respectively. Then there are n-1 lines each containing two integers: u v (0 ≤ u, v < n, u ≠ v) meaning that there is an edge from node u and v. Assume that the edges form a valid tree. Next line contains an integer q (1 ≤ q ≤ 105) followed by q lines each containing a query as described above.
Output
For each case, print the case number in a single line. Then for each query 0 i j, print the total number of genies in the nodes that occur in path i to j.
Sample Input | Output for Sample Input |
1
4 10 20 30 40 0 1 1 2 1 3 3 0 2 3 1 1 100 0 2 3 | Case 1: 90 170 |
题目大意:
给出N个点,每个点都有对应的点权值,我们现在有两种操作:
①0 x y表示查询从x到y的路径上所有的点权值的和。
②1 x y表示将x点的权值改成y.
思路:
直接树抛加上基础线段树操作即可。
没有难点。
#include<stdio.h>
#include<string.h>
#include<vector>
using namespace std;
int cnt;
vector<int>mp[35000];
int val[35000];
int depth[35000];
int son[35000];
int fa[35000];
int size[35000];
int Top[35000];
int dfn[35000];
/***************************/
#define lson l,m,rt*2
#define rson m+1,r,rt*2+1
int tree[55000*10];
void pushup(int rt)
{
tree[rt]=tree[rt<<1]+tree[rt<<1|1];
}
void update(int L,int R,int c,int l,int r,int rt)
{
if(L<=l&&r<=R)//覆盖的是区间~
{
tree[rt]=c;
return ;
}
int m=(l+r)/2;
if(L<=m)
{
update(L,R,c,lson);
}
if(m<R)
{
update(L,R,c,rson);
}
pushup(rt);
}
int Query(int L,int R,int l,int r,int rt)
{
if(L<=l&&r<=R)
{
return tree[rt];
}
else
{
int m=(l+r)>>1;
int ans=0;
if(L<=m)
{
ans+=Query(L,R,lson);
}
if(m<R)
{
ans+=Query(L,R,rson);
}
pushup(rt);
return ans;
}
}
void build( int l ,int r , int rt )
{
if( l == r )
{
tree[rt]=0;
return ;
}
else
{
int m = (l+r)>>1 ;
build(lson) ;
build(rson) ;
pushup(rt) ;
return ;
}
}
/***************************/
int n;
int Dfs(int u,int from,int d)
{
size[u]=1;depth[u]=d;son[u]=-1;fa[u]=from;
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(v==from)continue;
Dfs(v,u,d+1);
size[u]+=size[v];
if(son[u]==-1||size[v]>size[son[u]])
{
son[u]=v;
}
}
return size[u];
}
void Dfs2(int u,int from,int top)
{
Top[u]=top;dfn[u]=++cnt;
if(son[u]!=-1)
{
Dfs2(son[u],u,top);
}
for(int i=0;i<mp[u].size();i++)
{
int v=mp[u][i];
if(v==from||v==son[u])continue;
Dfs2(v,u,v);
}
}
void Work(int x,int y)
{
int sum=0;
int fx=Top[x],fy=Top[y];
while(fx!=fy)
{
if(depth[fx]<depth[fy])
{
swap(fx,fy);
swap(x,y);
}
sum+=Query(dfn[fx],dfn[x],1,n,1);
x=fa[fx];fx=Top[x];
}
if(depth[x]<depth[y])swap(x,y);
sum+=Query(dfn[y],dfn[x],1,n,1);
printf("%d\n",sum);
}
int main()
{
int t;
int kase=0;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
for(int i=1;i<=n;i++)scanf("%d",&val[i]);
for(int i=1;i<=n;i++)mp[i].clear();
for(int i=1;i<=n-1;i++)
{
int x,y;scanf("%d%d",&x,&y);
x++;y++;
mp[x].push_back(y);
mp[y].push_back(x);
}
cnt=0;
Dfs(1,-1,1);
Dfs2(1,-1,1);
build(1,n,1);
for(int i=1;i<=n;i++)update(dfn[i],dfn[i],val[i],1,n,1);
int m;
scanf("%d",&m);
printf("Case %d:\n",++kase);
while(m--)
{
int op,x,y;
scanf("%d%d%d",&op,&x,&y);
x++;
if(op==1)
{
update(dfn[x],dfn[x],y,1,n,1);
}
else
{
y++;
Work(x,y);
}
}
}
}