HAOI2015 树上操作

题目描述

有一棵点数为 N 的树,以点 1 为根,且树点有边权。然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a 。操作 2 :把某个节点 x 为根的子树中所有点的点权都增加 a 。操作 3 :询问某个节点 x 到根的路径中所有点的点权和。

输入输出格式

输入格式:

第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N-1 行每行三个正整数 fr, to , 表示该树中存在一条边 (fr, to) 。再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( 1-3 ) ,之后接这个操作的参数( x 或者 x a ) 。

输出格式:

对于每个询问操作,输出该询问的答案。答案之间用换行隔开。

输入输出样例

输入样例#1:

5 5
1 2 3 4 5
1 2
1 4
2 3
2 5
3 3
1 2 1
3 5
2 1 2
3 3
输出样例#1:

6
9
13

说明

对于 100% 的数据, N,M<=100000 ,且所有输入数据的绝对值都不

会超过 10^6 。

模板题就不多说啦,http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html 有介绍,我就是看这个懂得

#include <algorithm>
#include <cstdio>
#include <vector>
using namespace std;
const int maxn = 100000 + 10;
int cnt = 0,n,m,map[maxn],val[maxn],num[maxn],size[maxn],father[maxn],son[maxn],top[maxn],dep[maxn],w[maxn];
vector<int> edges[maxn];
inline void dfs1(int now,int f) {
    size[now] = 1;
    father[now] = f;
    dep[now] = dep[father[now]]+1;
    for (size_t i = 0;i < edges[now].size();i++)
        if (edges[now][i] != f) {
            dfs1(edges[now][i],now);
            size[now] += size[edges[now][i]];
            if (size[son[now]] < size[edges[now][i]] || !son[now]) son[now] = edges[now][i];
        }
}
inline void dfs2(int now,int ntop) {
    top[now] = ntop;
    num[now] = ++cnt;
    map[num[now]] = now;
    if (son[now]) dfs2(son[now],ntop);
    for (size_t i = 0;i < edges[now].size();i++)
        if (edges[now][i] != father[now] && edges[now][i] != son[now]) dfs2(edges[now][i],edges[now][i]);
}
struct seg { long long sum,mark,l,r; } tree[maxn*4];
inline void BuildTree(int l,int r,int root) {
    if (l == r) {
        tree[root].l = l;
        tree[root].r = r;
        tree[root].sum = val[map[l]];
        tree[root].mark = 0;
        return;
    }
    int mid = l+r>>1;
    BuildTree(l,mid,root<<1);
    BuildTree(mid+1,r,(root<<1)+1);
    tree[root].l = l;
    tree[root].r = r;
    tree[root].mark = 0;
    tree[root].sum = tree[root<<1].sum+tree[(root<<1)+1].sum;
}
inline void pushdown(int root) {
    if (tree[root].mark) {
        tree[root<<1].mark += tree[root].mark;
        tree[root<<1|1].mark += tree[root].mark;
        tree[root<<1].sum += tree[root].mark*(tree[root<<1].r-tree[root<<1].l+1);
        tree[root<<1|1].sum += tree[root].mark*(tree[root<<1|1].r-tree[root<<1|1].l+1);
        tree[root].mark = 0;
    }
}
inline void Update(int l,int r,int ql,int qr,int root,long long x) {
    if (ql > r || qr < l) return;
    if (ql <= l && qr >= r) {
        tree[root].mark += x;
        tree[root].sum += x*(r-l+1);
        return;
    }
    pushdown(root);
    int mid = l+r>>1;
    Update(l,mid,ql,qr,root<<1,x);
    Update(mid+1,r,ql,qr,root<<1|1,x);
    tree[root].sum = tree[root<<1].sum+tree[root<<1|1].sum;
}
inline long long Query(int l,int r,int ql,int qr,int root) {
    if (ql > r || qr < l) return 0;
    if (ql <= l && qr >= r) return tree[root].sum;
    pushdown(root);
    int mid = l+r>>1;
    return Query(l,mid,ql,qr,root<<1)+Query(mid+1,r,ql,qr,root<<1|1);
}
inline long long QueryEdges(int u,int v) {
    int topu = top[u];
    int topv = top[v];
    long long sum = 0;
    while (topu != topv) {
        if (dep[topu] < dep[topv]) {
            swap(topu,topv);
            swap(u,v);
        }
        sum += Query(1,cnt,num[topu],num[u],1);
        u = father[topu];
        topu = top[u];
    }
    if (dep[u] > dep[v]) swap(u,v);
    return sum+Query(1,cnt,num[u],num[v],1);
}
int main() {
    scanf("%d%d",&n,&m);
    for (int i = 1;i <= n;i++) scanf("%d",&val[i]);
    for (int i = 1,u,v;i < n;i++) {
        scanf("%d%d",&u,&v);
        edges[u].push_back(v);
        edges[v].push_back(u);
    }
    dfs1(1,0);
    dfs2(1,1);
    BuildTree(1,cnt,1);
    while (m--) {
        long long dispose,x,y;
        scanf("%lld%lld",&dispose,&x);
        if (dispose == 1) {
            scanf("%lld",&y);
            Update(1,cnt,num[x],num[x],1,y);
        } else if (dispose == 2) {
            scanf("%lld",&y);
            Update(1,cnt,num[x],num[x]+size[x]-1,1,y);
        } else if (dispose == 3) printf("%lld\n",QueryEdges(1,x));
    }
    return 0;
}

  

HAOI2015 树上操作的更多相关文章

  1. 【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树

    [BZOJ4034][HAOI2015]树上操作 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 ...

  2. bzoj千题计划242:bzoj4034: [HAOI2015]树上操作

    http://www.lydsy.com/JudgeOnline/problem.php?id=4034 dfs序,树链剖分 #include<cstdio> #include<io ...

  3. bzoj4034[HAOI2015]树上操作 树链剖分+线段树

    4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 6163  Solved: 2025[Submit][Stat ...

  4. 树剖||树链剖分||线段树||BZOJ4034||Luogu3178||[HAOI2015]树上操作

    题面:P3178 [HAOI2015]树上操作 好像其他人都嫌这道题太容易了懒得讲,好吧那我讲. 题解:第一个操作和第二个操作本质上是一样的,所以可以合并.唯一值得讲的点就是:第二个操作要求把某个节点 ...

  5. P3178 [HAOI2015]树上操作

    P3178 [HAOI2015]树上操作 思路 板子嘛,其实我感觉树剖没啥脑子 就是debug 代码 #include <bits/stdc++.h> #define int long l ...

  6. bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树

    4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 4352  Solved: 1387[Submit][Stat ...

  7. bzoj 4034: [HAOI2015]树上操作 (树剖+线段树 子树操作)

    4034: [HAOI2015]树上操作 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 6779  Solved: 2275[Submit][Stat ...

  8. BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 )

    BZOJ.4034 [HAOI2015]树上操作 ( 点权树链剖分 线段树 ) 题意分析 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 ...

  9. 洛谷P3178 [HAOI2015]树上操作(dfs序+线段树)

    P3178 [HAOI2015]树上操作 题目链接:https://www.luogu.org/problemnew/show/P3178 题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边 ...

随机推荐

  1. 【干货】Chrome插件(扩展)开发全攻略(不点进来看看你肯定后悔)

    写在前面 我花了将近一个多月的时间断断续续写下这篇博文,并精心写下完整demo,写博客的辛苦大家懂的,所以转载务必保留出处.本文所有涉及到的大部分代码均在这个demo里面:https://github ...

  2. Jenkins集成源码静态分析工具

    1.static code analysis插件说明 Jenkins提供了插件"static code analysis",该插件搜集不同的分析结果,并集合显示出来. 实际上,我们 ...

  3. 使用curl模拟ip和来源进行网站采集的实现方法

    对于限制了ip和来源的网站,使用正常的采集方式是不行的.本文将介绍一种方法,使用php的curl类实现模拟ip和来源,实现采集限制ip和来源的网站. 1.设置页面限制ip和来源访问 server.ph ...

  4. 中缀表达式变后缀表达式、后缀表达式(逆波兰)求值(python版本)

    定义: 中缀表达式: 在通常的表达式中,二元运算符总是置于与之相关的两个运算对象之间,这种表示法也称为中缀表达式 后缀表达式: 又叫逆波兰表达式 ,不包含括号,运算符放在两个运算对象的后面,所有的计算 ...

  5. 一个简单的java贷款程序

    代码如下: //计算贷款package ClassDemo;import javax.swing.JOptionPane; public class ComputeLoan { public stat ...

  6. rsync安装及其配置

    服务端配置安装 服务器 第一步: 下载rsync 安装包(在线安装或者线下安装)         wget https://download.samba.org/pub/rsync/rsync-3.1 ...

  7. VUE 分页组件

    <!DOCTYPE html><html> <head> <meta charset="UTF-8"> <title>& ...

  8. 关于华为P9手机的解锁、刷Recovery、获取Root、安装Busybox,以及升级降级的全过程(和一些错误的解决方法)

    我有一部华为P9手机,型号EVA-TL00,属于移动定制机.用了半年多了,想给手机添加一些功能,发现有些功能必须Root之后才能用代码实现,所以动了Root的打算. 一.手机解锁.(不解锁则无法对手机 ...

  9. dotpeek的导出

    在开始写之前先说明下,搜了很久的度娘,就是没找到dotpeek的导出功能,····,看来用的人不多, ------------------------------------------------- ...

  10. 【.net 深呼吸】自己动手来写应用程序设置类

    在开始装逼之前,老周先说明一件事.有人说老周写的东西太简单了,能不能写点复杂点.这问题就来了,要写什么东西才叫“复杂”?最重要的是,写得太复杂了,一方面很多朋友看不懂,另一方面,连老周自己也不知道怎么 ...