Codeforces 384E 线段树+dfs序

题目链接:点击打开链接

题意:

给定n个点,m个询问的无向树(1为根)

下面n个数表示每个点的权值

下面n-1行给出树

操作1:x点权值+v, x的第 i & 1 的儿子-v, 第 !(i&1) 的儿子+v

操作2:询问x点权值

dfs把树转成序列

根据深度把点分成2组

分别用线段树维护。。

然后Y一下

#include<stdio.h>
#include<string.h>
#include<iostream>
#include<algorithm>
#include<math.h>
#include<set>
#include<queue>
#include<vector>
#include<map>
using namespace std;
#define ll __int64
#define L(x) (x<<1)
#define R(x) (x<<1|1)
#define N 201000
ll n ,m;
inline ll Mid(ll a,ll b){return (a+b)>>1;}
struct Edge{
    ll from, to, nex;
}edge[N<<1];
ll head[N], edgenum;
void add(ll u,ll v){
    Edge E = {u,v,head[u]};
    edge[edgenum] = E;
    head[u] = edgenum++;
}
ll in[N], out[N], fa[N], Time, dep[N], V[N];
void dfs(ll u, ll father, ll deep){
    fa[u] = father;
    dep[u] = deep;
    in[u] = ++Time;

    for(ll i = head[u];~i; i = edge[i].nex){
        ll v = edge[i].to;      if(v==father)continue;
        dfs(v,u,deep+1);
    }
    out[u] = Time;
}
struct node{
    struct E{
        ll l, r, val, lazy;
    }t[N<<2];
    void push_down(ll id){
        if(t[id].l==t[id].r || t[id].lazy == 0)return ;
        t[L(id)].val += t[id].lazy;
        t[R(id)].val += t[id].lazy;
        t[L(id)].lazy+=t[id].lazy;
        t[R(id)].lazy+=t[id].lazy;
        t[id].lazy = 0;
    }
    void build(ll l, ll r, ll id){
        t[id].l = l; t[id].r = r;
        t[id].val = 0;
        t[id].lazy = 0;
        if(l==r)return;
        ll mid = Mid(l,r);
        build(l,mid,L(id));build(mid+1,r,R(id));
    }
    void update(ll l, ll r,ll val,ll id){
        push_down(id);
        if(l == t[id].l && t[id].r == r) { t[id].val += val; t[id].lazy = val; return ;}

        ll mid = Mid(t[id].l, t[id].r);
        if(mid<l)update(l,r,val,R(id));
        else if(r<=mid)update(l,r,val,L(id));
        else {
            update(l,mid,val,L(id));
            update(mid+1,r,val,R(id));
        }
    }
    ll query(ll l, ll r, ll id){
        push_down(id);
        if(l == t[id].l && t[id].r == r)return t[id].val;

        ll mid = Mid(t[id].l, t[id].r);
        if(mid<l)return query(l,r,R(id));
        else if(r<=mid)return query(l,r,L(id));
        return query(l,mid,L(id))+query(mid+1,r,R(id));
    }
}tree[2];
ll query(ll u){
    ll ans = tree[dep[u]&1].query(in[u],in[u],1);
    return ans;
}
void init(){Time = 0; memset(head, -1, sizeof head); edgenum = 0;}
int main(){
    ll i, j, u, v;
    while(cin>>n>>m) {
        init();
        for(i=1;i<=n;i++)cin>>V[i];
        for(i=1;i<n;i++){
            cin>>u>>v;
            add(u,v);
            add(v,u);
        }
        dfs(1,-1,1);
        tree[0].build(1,n,1);
        tree[1].build(1,n,1);
        while(m--){
            cin>>u;
            if(u==1) {
                cin>>u>>v;
                tree[dep[u]&1].update(in[u],out[u],v,1);
                if(in[u]<out[u])
                    tree[!(dep[u]&1)].update(in[u]+1,out[u],-v,1);
            }
            else {
                cin>>u;
                cout<<query(u)+V[u]<<endl;
            }
        }
    }
    return 0;
}

Codeforces 384E 线段树+dfs序

时间: 2024-10-29 19:09:45

Codeforces 384E 线段树+dfs序的相关文章

Tsinsen A1505. 树(张闻涛) 倍增LCA,可持久化线段树,DFS序

题目:http://www.tsinsen.com/A1505 A1505. 树(张闻涛) 时间限制:1.0s   内存限制:512.0MB 总提交次数:196   AC次数:65   平均分:58.62 将本题分享到: 查看未格式化的试题   提交   试题讨论 试题来源 2013中国国家集训队第二次作业 问题描述 给定一棵N个节点的树,每个点有一个权值,有M个询问(a,b,c)若a 为1,回答b到c路径上的最小权值,若a为2,回答b到c路径上的最大权值,若a为3,回答b到c路径上的所有权值的

线段树+dfs序(Apple Tree )(Assign the task )

线段树+dfs序 给定一棵n个节点的树,m次查询,每次查询需要求出某个节点深度为h的所有子节点. 作为预处理,首先将树的所有节点按深度保存起来,每个深度的所有节点用一个线性结构保存,每个深度的节点相对顺序要和前序遍历一致. 然后从树的根节点进行dfs,对于每个节点记录两个信息,一个是dfs进入该节点的时间戳in[id],另一个是dfs离开该节点的时间戳out[id]. 最后对于每次查询,求节点v在深度h的所有子节点,只需将深度为h并且dfs进入时间戳在in[v]和out[v]之间的所有节点都求出

HDU 5692 线段树+dfs序

Snacks Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 1779    Accepted Submission(s): 427 Problem Description 百度科技园内有n 个零食机,零食机之间通过n−1 条路相互连通.每个零食机都有一个值v ,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v

Codeforces 877E - Danil and a Part-time Job 线段树+dfs序

给一个有根树,1e5个节点,每个节点有权值0/.1,1e5操作:1.将一个点的子树上所有点权值取反2.查询一个点的子树的权值和 题解: 先深搜整颗树,用dfs序建立每个点对应的区间,等于把树拍扁成一个数列,每次操作从就对点变成了对区间然后就是裸线段树 注意拍扁后的节点标号和原来的树节点标号是不等价的,要映射一下 #include <bits/stdc++.h> #define endl '\n' #define ll long long #define fi first #define se

K. Random Numbers(Gym 101466K + 线段树 + dfs序 + 快速幂 + 唯一分解)

题目链接:http://codeforces.com/gym/101466/problem/K 题目: 题意: 给你一棵有n个节点的树,根节点始终为0,有两种操作: 1.RAND:查询以u为根节点的子树上的所有节点的权值的乘积x,及x的因数个数. 2.SEED:将节点u的权值乘以x. 思路: 比赛时少看了因数不大于13这句话,然后本题难度增加数倍,肝了两个小时都没肝出来,对不起队友啊,今天的组队训练赛实力背锅…… 这题一眼线段树,由于是对一棵子树进行处理,因此我们采用常规套路,借助dfs序将子树

HDU5692(线段树+dfs序)

Snacks Time Limit:5000MS     Memory Limit:65536KB     64bit IO Format:%I64d & %I64u Submit Status Description 百度科技园内有n个零食机,零食机之间通过n−1条路相互连通.每个零食机都有一个值v,表示为小度熊提供零食的价值. 由于零食被频繁的消耗和补充,零食机的价值v会时常发生变化.小度熊只能从编号为0的零食机出发,并且每个零食机至多经过一次.另外,小度熊会对某个零食机的零食有所偏爱,要求

【BZOJ-3779】重组病毒 LinkCutTree + 线段树 + DFS序

3779: 重组病毒 Time Limit: 20 Sec  Memory Limit: 512 MBSubmit: 224  Solved: 95[Submit][Status][Discuss] Description 黑客们通过对已有的病毒反编译,将许多不同的病毒重组,并重新编译出了新型的重组病毒.这种病毒的繁殖和变异能力极强.为了阻止这种病毒传播,某安全机构策划了一次实验,来研究这种病毒.实验在一个封闭的局域网内进行.局域网内有n台计算机,编号为1~n.一些计算机之间通过网线直接相连,形

【BZOJ-3306】树 线段树 + DFS序

3306: 树 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 792  Solved: 262[Submit][Status][Discuss] Description 给定一棵大小为 n 的有根点权树,支持以下操作: • 换根 • 修改点权      • 查询子树最小值 Input 第一行两个整数 n, Q ,分别表示树的大小和操作数. 接下来n行,每行两个整数f,v,第i+1行的两个数表示点i的父亲和点i的权.保证f < i.如 果f = 0

【codevs1228】苹果树【线段树+dfs序】

题目描述 Description 在卡卡的房子外面,有一棵苹果树.每年的春天,树上总会结出很多的苹果.卡卡非常喜欢吃苹果,所以他一直都精心的呵护这棵苹果树.我们知道树是有很多分叉点的,苹果会长在枝条的分叉点上面,且不会有两个苹果结在一起.卡卡很想知道一个分叉点所代表的子树上所结的苹果的数目,以便研究苹果树哪些枝条的结果能力比较强. 卡卡所知道的是,每隔一些时间,某些分叉点上会结出一些苹果,但是卡卡所不知道的是,总会有一些调皮的小孩来树上摘走一些苹果. 于是我们定义两种操作: C x 表示编号为x