萌新刚学 OI,血战无法战胜

Path Queries

时间限制: 2000\ \mathrm{ms}
空间限制: 262144\ \mathrm{KB}

题目描述

给定一棵有根树,包含 n 个节点。节点编号为 1n,节点 1 为根节点。每个节点都有一个值。

您的任务是处理以下类型的查询:

  • 将节点 s 的值更改为 x
  • 计算从根到节点 s 的路径上的值的总和。

输入格式

第一个输入行包含两个整数 nq:节点和查询的数量。节点编号为 1,2,\cdots,n

下一行有 n 个整数 v_1,v_2,\cdots,v_n:每个节点的值。

然后有 n−1 条线描述边缘。每一行包含两个整数 ab:节点 ab 之间有一条边。

最后,有 q 行描述查询。每个查询的格式为 1 s x2 s

计算从根到节点 s 的路径上的值的总和。

输出格式

对于类型 2 的查询,请输出结果。

样例

Input1

5 3
4 2 5 2 1
1 2
1 3
3 4
3 5
2 4
1 3 2
2 4

Output1

11
8

数据范围

1≤n,q≤2\times 10^5

1≤a,b,s≤n

1≤v_i,x≤10^9

我的代码

#include<bits/stdc++.h>
#define I using
#define AK namespace
#define IOI std
#define i_ak return
#define ioi  0
#define i_will signed
#define ak main
#define IMO ()
#define int long long
I AK IOI;
const int MAXN=2e5+5;
vector<int>adj[MAXN];
int values[MAXN],sum[MAXN],parent[MAXN],n,q;
void dfs(int node,int par){
    parent[node]=par;
    sum[node]=values[node];
    if(par!=-1)sum[node]+=sum[par];
    for(int child:adj[node])if(child!=par)dfs(child,node);
}
void update(int s,int x){
    if(values[s]==x)return;
    int diff=x-values[s];
    values[s]=x;
    while(s!=-1){
        sum[s]+=diff;
        s=parent[s];
    }
}
int query(int s){
    return sum[s];
}
i_will ak IMO{
    cin>>n>>q;
    for(int i=1;i<=n;i++)cin>>values[i];
    for(int i=0;i<n-1;i++){
        int a,b;
        cin>>a>>b;
        adj[a].push_back(b);
        adj[b].push_back(a);
    }
    dfs(1,-1);
    for(int i=0;i<q;i++){
        int type,s;
        cin>>type>>s;
        if(type==1){
            int x;
            cin>>x;
            update(s,x);
        }
		else cout<<query(s)<<endl;
    }
    i_ak ioi;
}

样例不过。

这时间还有人在不会是和我一样在写五一作业吧

@卡皮巴拉 不是,我是在做题,能帮我调题骂?

这是…线段树?

@卡皮巴拉 不是,是树状数组

o,sorry,做线段树做魔怔了

@卡皮巴拉 但是感觉也不太有用树状数组

这个数组是记录什么的

@卡皮巴拉 这是记录这个结点的父亲

这是树,不是无向图

@卡皮巴拉 但是他只是说这代表 ab 有一条边但是没说谁是父亲

但你这里明显会把父节点再dfs一遍

@卡皮巴拉 而且这不影响吧

@卡皮巴拉 改了,还是不行

#include<bits/stdc++.h>
#define I using
#define AK namespace
#define IOI std
#define i_ak return
#define ioi  0
#define i_will signed
#define ak main
#define IMO ()
#define int long long
I AK IOI;
const int MAXN=2e5+5;
vector<int>adj[MAXN];
int values[MAXN],sum[MAXN],parent[MAXN],n,q;
void dfs(int node,int par){
    parent[node]=par;
    sum[node]=values[node];
    if(par!=-1)sum[node]+=sum[par];
    for(int child:adj[node])if(child!=par)dfs(child,node);
}
void update(int s,int x){
    if(values[s]==x)return;
    int diff=x-values[s];
    values[s]=x;
    while(s!=-1){
        sum[s]+=diff;
        s=parent[s];
    }
}
int query(int s){
    return sum[s];
}
i_will ak IMO{
    cin>>n>>q;
    for(int i=1;i<=n;i++)cin>>values[i];
    for(int i=0;i<n-1;i++){
        int a,b;
        cin>>a>>b;
        adj[a].push_back(b);
    }
    dfs(1,-1);
    for(int i=0;i<q;i++){
        int type,s;
        cin>>type>>s;
        if(type==1){
            int x;
            cin>>x;
            update(s,x);
        }
		else cout<<query(s)<<endl;
    }
    i_ak ioi;
}

现在TLE了

题目链接发一个

@卡皮巴拉 智灵提高班第六课 - 树状数组/字典树 - 信友队

玩了,用瞪眼法硬是没看出来

@卡皮巴拉

@卡皮巴拉 欸?人呢?