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. windows 10 下使用 binwalk

    刚接触CTF没什么经验,菜鸟一只很多题不会做,就在网上看大佬写的Write up.发现经常会用到一个小工具--binwalk.binwalk在kali系统里是一个自带的工具,但windows可没有.之 ...

  2. 使用C#创建简单的WCF服务

    一.开发环境 操作系统:Windows 10 开发环境:VS2015 编程语言:C# IIS版本:10.0.0.0 二.添加WCF服务.Internet Information Services(II ...

  3. CentOS 6.9上安装mysql-5.6.36

    CentOS 6.9上安装mysql-5.6.36 1.准备数据存放的文件系统 新建一个逻辑卷,并将其挂载至特定目录即可.这里不再给出过程. 这里假设其逻辑卷的挂载目录为/data,而后需要创建/da ...

  4. Servlet端 接收不到4096,8192长度的JSON参数

    Servlet端的日志显示,客户端传过来的JSON参数是空值. 但是在客户端的日志显示,已将JSON参数传送过去. 经调查发现,加减1位后的JSON参数均可以正常传送. 只有8192,4096长度的J ...

  5. 【SqlServer系列】开启Sqlserver远程访问

    1   概述 已发布[SqlServer系列]文章如下: [SqlServer系列]SQLSERVER安装教程 [SqlServer系列]数据库三大范式 [SqlServer系列]表单查询 [SqlS ...

  6. docker~为什么没人说说.dockerignore

    回到目录 最近一直专注于docker的开发之中,而在使用Dockerfile时发现有个问题,当你的发布目录只能是obj\Docker\publish,而指向其它目录dockefile并不认它,只有如何 ...

  7. 基于腾讯Centos7云服务器搭建SVN版本控制库

    基于腾讯Centos7云服务器搭建SVN版本控制库 最近在和小伙伴组队参加一个关于人工智能的比赛,无奈不知道怎么处理好每个人的代码托管问题,于是找到了晚上免费svn托管服务器的服务,但是所给的免费空间 ...

  8. 学习笔记TF027:卷积神经网络

    卷积神经网络(Convolutional Neural Network,CNN),可以解决图像识别.时间序列信息问题.深度学习之前,借助SIFT.HoG等算法提取特征,集合SVM等机器学习算法识别图像 ...

  9. 【微信小程序开发教程】如何显示群名称?

    今年 5 月份的时候,微信宣布:「为了更好的针对群场景提供个性化服务,当用户在群聊中点击小程序分享卡片时,小程序支持开发者获取群 ID 和群名称」.但随后没多久,发现小程序只返回了群 ID,并没有给我 ...

  10. 初学Python(八)——迭代

    初学Python(八)——迭代 初学Python,主要整理一些学习到的知识点,这次是迭代. # -*- coding:utf-8 -*- from collections import Iterabl ...