题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=4034

题意:中文题面

思路:树链剖分入门题。 剖分后就是一个简单的区间更新和区间求和问题。用线段树去维护一下。 由于有一个操作是关于子树的,可以用DFS序来求,但是由于剖分后的序列都是连续的,所以只需要记录下返回当前根时前一个点的位置即可进行子树操作。

#define _CRT_SECURE_NO_DEPRECATE
#include<iostream>
#include<cstring>
#include<string>
#include<algorithm>
#include<stdio.h>
#include<queue>
#include<vector>
#include<stack>
#include<map>
#include<set>
#include<time.h>
#include<cmath>
#include<sstream>
#include<assert.h>
using namespace std;
#define L(x) x<<1
#define R(x) x<<1|1
typedef long long int LL;
const int inf = 0x3f3f3f3f;
const LL INF = 0x3f3f3f3f3f3f3f3fLL;
const int MAXN = + ;
int val[MAXN], head[MAXN], tot, cnt;
struct Edge{
int to,next;
Edge(int _to = , int _next = ) :to(_to), next(_next){};
}Edges[MAXN * ];
void add(int u, int v){
Edges[tot].to = v;
Edges[tot].next = head[u];
head[u] = tot++;
}
int id[MAXN], endid[MAXN], son[MAXN], deep[MAXN], size[MAXN], fa[MAXN], reid[MAXN], top[MAXN];
void Init(){
tot = ; cnt = ;
memset(head, -, sizeof(head));
memset(son, -, sizeof(son));
}
void DFS1(int u, int p,int dep){
fa[u] = p; size[u] = ; deep[u] = dep;
for (int i = head[u]; i != -; i = Edges[i].next){
if (Edges[i].to != p){
DFS1(Edges[i].to, u,dep+);
size[u] += size[Edges[i].to];
if (son[u] == - || size[Edges[i].to] > size[son[u]]){
son[u] = Edges[i].to;
}
}
}
}
void DFS2(int u, int tp){
id[u] = ++cnt; reid[id[u]] = u; top[u] = tp;
if (son[u] == -){
endid[u] = cnt;
return;
}
DFS2(son[u], tp);
for (int i = head[u]; i != -; i = Edges[i].next){
if (son[u] != Edges[i].to&&Edges[i].to != fa[u]){
DFS2(Edges[i].to, Edges[i].to);
}
}
endid[u] = cnt;
}
struct Node{
int st, ed;
LL sum, lazy;
}Seg[MAXN * ];
void Build(int l, int r, int k){
Seg[k].st = l; Seg[k].ed = r; Seg[k].lazy = ;
if (l == r){
Seg[k].sum = val[reid[l]];
return;
}
int mid = (l + r) / ;
Build(l, mid, L(k)); Build(mid + , r, R(k));
Seg[k].sum = Seg[L(k)].sum + Seg[R(k)].sum;
}
void pushUp(int k){
Seg[k].sum = Seg[L(k)].sum + Seg[R(k)].sum;
}
void pushDown(int k){
if (Seg[k].lazy){
Seg[L(k)].sum += 1LL*Seg[k].lazy*(Seg[L(k)].ed - Seg[L(k)].st + );
Seg[L(k)].lazy += Seg[k].lazy;
Seg[R(k)].sum += 1LL*Seg[k].lazy*(Seg[R(k)].ed - Seg[R(k)].st + );
Seg[R(k)].lazy += Seg[k].lazy;
Seg[k].lazy = ;
}
}
void Add(int l, int r, int k,int val){
if (Seg[k].st == l&&Seg[k].ed == r){
Seg[k].lazy += val;
Seg[k].sum += 1LL * val * (r - l + );
return;
}
pushDown(k);
if (r <= Seg[L(k)].ed){
Add(l, r, L(k),val);
}
else if (l >= Seg[R(k)].st){
Add(l, r, R(k),val);
}
else{
Add(l, Seg[L(k)].ed, L(k), val);
Add(Seg[R(k)].st, r, R(k), val);
}
pushUp(k);
}
LL Query(int l, int r, int k){
if (Seg[k].st == l&&Seg[k].ed == r){
return Seg[k].sum;
}
pushDown(k);
LL sum = ;
if (r <= Seg[L(k)].ed){
sum=Query(l, r, L(k));
}
else if (l >= Seg[R(k)].st){
sum=Query(l, r, R(k));
}
else{
sum=Query(l, Seg[L(k)].ed, L(k)) + Query(Seg[R(k)].st, r, R(k));
}
pushUp(k);
return sum;
}
LL Query(int x){
LL ans = ;
while (top[x]!=){
ans += Query(id[top[x]], id[x],);
x = fa[top[x]];
}
ans += Query(,id[x], );
return ans;
}
int main(){
//#ifdef kirito
// freopen("in.txt", "r", stdin);
// freopen("out.txt", "w", stdout);
//#endif
// int start = clock();
int n, m;
while (~scanf("%d%d",&n,&m)){
Init();
for (int i = ; i <= n; i++){
scanf("%d", &val[i]);
}
for (int i = ; i < n; i++){
int u, v;
scanf("%d%d", &u, &v);
add(u, v); add(v, u);
}
DFS1(, , ); DFS2(, );
Build(, n, );
while (m--){
int ope, x, a;
scanf("%d", &ope);
switch (ope)
{
case :scanf("%d%d", &x, &a); Add(id[x],id[x] , , a); break;
case :scanf("%d%d", &x, &a); Add(id[x], endid[x], , a); break;
default: scanf("%d", &x); printf("%lld\n", Query(x)); break;
}
}
}
//#ifdef LOCAL_TIME
// cout << "[Finished in " << clock() - start << " ms]" << endl;
//#endif
return ;
}

BZOJ 4034 树链剖分的更多相关文章

  1. BZOJ 4326 树链剖分+二分+差分+记忆化

    去年NOIP的时候我还不会树链剖分! 还是被UOJ 的数据卡了一组. 差分的思想还是很神啊! #include <iostream> #include <cstring> #i ...

  2. BZOJ 1036 && 树链剖分

    还是太弱啊..各种数据结构只听过名字却没有一点概念..树链剖分也在这个范畴..今天来进一步深化一下教育改革推进全民素质提高. 性质 忘了在哪里看到的一篇blog有一句话讲得非常好,树链剖分不是一种数据 ...

  3. bzoj 3083 树链剖分

    首先我们先将树提出一个根变成有根树,那么我们可以通过树链剖分来实现对于子树的最小值求解,那么按照当前的根和询问的点的相对位置关系我们可以将询问变成某个子树和或者除去某颗子树之后其余的和,前者直接询问区 ...

  4. bzoj 2243 树链剖分

    2013-11-19 16:21 原题传送门http://www.lydsy.com/JudgeOnline/problem.php?id=2243 树链剖分,用线段树记录该区间的颜色段数,左右端点颜 ...

  5. bzoj 4196 树链剖分 模板

    [Noi2015]软件包管理器 Time Limit: 10 Sec  Memory Limit: 512 MBSubmit: 2135  Solved: 1232[Submit][Status][D ...

  6. BZOJ 4811 树链剖分+线段树

    思路: 感觉这题也可神了.. (还是我太弱) 首先发现每一位不会互相影响,可以把每一位分开考虑,然后用树链剖分或者LCT维护这个树 修改直接修改,询问的时候算出来每一位填0,1经过这条链的变换之后得到 ...

  7. BZOJ 2286 树链剖分+DFS序+虚树+树形DP

    第一次学习虚树,就是把无关的点去掉.S里维护一条链即可. #include <iostream> #include <cstring> #include <cstdio& ...

  8. BZOJ 3083 树链剖分+倍增+线段树

    思路: 先随便选个点 链剖+线段树 1操作 就直接改root变量的值 2操作 线段树上改 3操作 分成三种情况 1.new root = xx 整个子树的min就是ans 2. lca(new roo ...

  9. BZOJ 2836 树链剖分+线段树

    思路: 链剖+线段树裸题 重链的标号就是DFS序 所以查子树的时候每回就 query(change[x],change[x]+size[x]-1) 就好了 剩下的应该都会吧.. //By Sirius ...

随机推荐

  1. Apache HttpClient之fluent API的使用

    该方法为Apache HttpClient 4.5以上的版本支持,在官网有明确的说明. 对比以前的方式,其优点是代码更简洁,同时为线程安全的.仅举一个最简单的post栗子 JAR包信息: <de ...

  2. Web截屏插件

    官方网站:http://www.ncmem.com 官方博客:http://www.cnblogs.com/xproer 产品首页:http://www.ncmem.com/webplug/scppr ...

  3. [CSP-S模拟测试]:太阳神(莫比乌斯反演)

    题目描述 太阳神拉很喜欢最小公倍数,有一天他想到了一个关于最小公倍数的题目.求满足如下条件的数对$(a,b)$对数:$a,b$均为正整数且$a,b\leqslant n$而$lcm(a,b)>n ...

  4. Centos6.5在线配置安装Java环境与Tomcat环境

        书写此文一来记录环境,以便后期查看使用,Linux环境下配置centos与Java开发环境 本文环境:虚拟机系统centos6.5   链接工具:xshell脚本链接工具 一.安装Java开发 ...

  5. TimeInOfficePresent

    w x <- c(52, 30, 10, 8)labels <- c("分析思考", "写代码.调试", "沟通", " ...

  6. ImportError: libsybdb.so.5: cannot open shared object file: No such file or directory pymssql linux 问题解决 搭建驱动

    [root@hadoop1 nlp]# python sqlserver_t.py Traceback (most recent call last):  File "sqlserver_t ...

  7. matlab: undocumented sprintfc

    今天本想找一个类似于 R 中 paste 的 matlab 函数, 结果在 stackoverflow 上找到一个叫 sprintfc 的函数 (http://stackoverflow.com/qu ...

  8. 137、TensorFlow使用TextCNN进行文本分类

    下面是分类的主函数入口 #! /usr/bin/env python import tensorflow as tf import numpy as np import os import time ...

  9. 知道css有个content属性吗?有什么作用?有什么应用?

    css的content属性专门应用在 before/after 伪元素上,用来插入生成内容.最常见的应用是利用伪类清除浮动. //一种常见利用伪类清除浮动的代码 .clearfix:after { c ...

  10. linux暴露端口可以被外部访问

    linux暴露端口可以被外部访问,把端口号换成要暴露的端口:/sbin/iptables -I INPUT -p tcp --dport 3306 -j ACCEPT Centos 7 开启端口Cen ...