[题目链接]

https://www.lydsy.com/JudgeOnline/problem.php?id=2836

[算法]

树链剖分

时间复杂度 : O(NlogN ^ 2)

[代码]

#include<bits/stdc++.h>
using namespace std;
#define MAXN 100010
typedef long long LL; struct edge
{
int to , nxt;
} e[MAXN << ]; int n , tot , timer;
int head[MAXN] , size[MAXN] , son[MAXN] , fa[MAXN] , dfn[MAXN] , depth[MAXN] , top[MAXN]; template <typename T> inline void chkmax(T &x , T y) { x = max(x , y); }
template <typename T> inline void chkmin(T &x , T y) { x = min(x , y); }
template <typename T> inline void read(T &x)
{
T f = ; x = ;
char c = getchar();
for (; !isdigit(c); c = getchar()) if (c == '-') f = -f;
for (; isdigit(c); c = getchar()) x = (x << ) + (x << ) + c - '';
x *= f;
}
struct Segment_Tree
{
struct Node
{
int l , r;
LL sum , tag;
} Tree[MAXN << ];
inline void build(int index , int l , int r)
{
Tree[index].l = l;
Tree[index].r = r;
Tree[index].tag = Tree[index].sum = ;
if (l == r) return;
int mid = (l + r) >> ;
build(index << , l , mid);
build(index << | , mid + , r);
}
inline void pushdown(int index)
{
int l = Tree[index].l , r = Tree[index].r;
int mid = (l + r) >> ;
Tree[index << ].sum += (mid - l + ) * Tree[index].tag;
Tree[index << | ].sum += (r - mid) * Tree[index].tag;
Tree[index << ].tag += Tree[index].tag;
Tree[index << | ].tag += Tree[index].tag;
Tree[index].tag = ;
}
inline void update(int index)
{
Tree[index].sum = Tree[index << ].sum + Tree[index << | ].sum;
}
inline void modify(int index , int l , int r , LL value)
{
if (Tree[index].l == l && Tree[index].r == r)
{
Tree[index].sum += value * (r - l + );
Tree[index].tag += value;
return;
}
pushdown(index);
int mid = (Tree[index].l + Tree[index].r) >> ;
if (mid >= r) modify(index << , l , r , value);
else if (mid + <= l) modify(index << | , l , r , value);
else
{
modify(index << , l , mid , value);
modify(index << | , mid + , r , value);
}
update(index);
}
inline LL query(int index , int l , int r)
{
if (Tree[index].l == l && Tree[index].r == r) return Tree[index].sum;
pushdown(index);
int mid = (Tree[index].l + Tree[index].r) >> ;
if (mid >= r) return query(index << , l , r);
else if (mid + <= l) return query(index << | , l , r);
else return query(index << , l , mid) + query(index << | , mid + , r);
}
} SGT;
inline void addedge(int u , int v)
{
++tot;
e[tot] = (edge){v , head[u]};
head[u] = tot;
}
inline void dfs1(int u)
{
son[u] = -;
size[u] = ;
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == fa[u]) continue;
fa[v] = u;
depth[v] = depth[u] + ;
dfs1(v);
size[u] += size[v];
if (son[u] == - || size[v] > size[son[u]]) son[u] = v;
}
}
inline void dfs2(int u , int tp)
{
dfn[u] = ++timer;
top[u] = tp;
if (son[u] != -) dfs2(son[u] , tp);
for (int i = head[u]; i; i = e[i].nxt)
{
int v = e[i].to;
if (v == fa[u] || v == son[u]) continue;
dfs2(v , v);
}
}
inline void modify(int u , int v , LL d)
{
int tu = top[u] , tv = top[v];
while (tu != tv)
{
if (depth[tu] > depth[tv])
{
swap(u , v);
swap(tu , tv);
}
SGT.modify( , dfn[tv] , dfn[v] , d);
v = fa[tv]; tv = top[v];
}
if (depth[u] > depth[v]) swap(u , v);
SGT.modify(, dfn[u] , dfn[v] , d);
} int main()
{ scanf("%d" , &n);
for (int i = ; i < n; i++)
{
int u , v;
scanf("%d%d" , &u , &v);
addedge(u , v);
fa[v] = u;
}
dfs1();
dfs2( , );
SGT.build( , , n);
int q;
scanf("%d" , &q);
while (q--)
{
char op[];
scanf("%s" , &op);
if (op[] == 'A')
{
int u , v;
LL d;
scanf("%d%d%lld" , &u , &v , &d);
modify(u , v , d);
} else
{
int u;
scanf("%d" , &u);
printf("%lld\n" , SGT.query( , dfn[u] , dfn[u] + size[u] - ));
}
} return ;
}

[SHOI 2012] 魔法树的更多相关文章

  1. 洛谷 3833 SHOI 2012 魔法树

    [题解] 树链剖分模板题.. #include<cstdio> #include<algorithm> #include<queue> #define N 5000 ...

  2. noip模拟赛(一)魔法树

    魔法树 (mahou.pas/c/cpp) [问题描述] 魔法使moreD在研究一棵魔法树. 魔法树顾名思义,这货是一棵树,奇葩的是魔法树上的每一条边都拥有一个魔法属性,如果不那么奇葩就不是moreD ...

  3. shoi 魔法树

    Harry Potter新学了一种魔法:可以改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的新法术.这棵果树共有N个节点,其中节点0是根节点,每个节点u的父亲记为fa[u],保证有fa ...

  4. [bzoj2836] 魔法树

    俩操作:增加路径上的点的权值.查询子树的权值和. 想了想似乎只能树链剖分了..好久没写链剖+数据结构了TAT 一开始没开LL炸了一发(明明有想到的..我果然是傻逼= = #include<cst ...

  5. P3833 [SHOI2012]魔法树

    思路 树剖板子 注意给出点的编号是从零开始的 代码 #include <cstdio> #include <algorithm> #include <cstring> ...

  6. 解题:SHOI 2012 回家的路

    题面 完了,做的时候已经想不起来分层图这个东西了QAQ 对于这种“多种”路径加中转站的题,还有那种有若干次“特殊能力”的题,都可以考虑用分层图来做 显然只需要记录所有的中转站+起点终点,然后拆出横竖两 ...

  7. [洛谷P3833][SHOI2012]魔法树

    题目大意:给一棵树,路径加,子树求和 题解:树剖 卡点:无 C++ Code: #include <cstdio> #include <iostream> #define ma ...

  8. 【树链剖分】【dfs序】【线段树】bzoj2836 魔法树

    这道题告诉我们:树链剖分的重标号就是dfs序. #include<cstdio> #include<algorithm> using namespace std; #defin ...

  9. 树链剖分【洛谷P3833】 [SHOI2012]魔法树

    P3833 [SHOI2012]魔法树 题目描述 Harry Potter 新学了一种魔法:可以让改变树上的果子个数.满心欢喜的他找到了一个巨大的果树,来试验他的新法术. 这棵果树共有N个节点,其中节 ...

随机推荐

  1. 洛谷 P2831 愤怒的小鸟

    P2831 愤怒的小鸟 题目描述 Kiana 最近沉迷于一款神奇的游戏无法自拔. 简单来说,这款游戏是在一个平面上进行的. 有一架弹弓位于 (0,0)(0,0) 处,每次 Kiana 可以用它向第一象 ...

  2. php执行超时(nginx,linux环境)

    与下面的参数有关 nginx: fastcgi_connect_timeout fastcgi_read_timeout fastcgi_send_timeout php-fpm:request_te ...

  3. 深入GCD(五):资源竞争

    概述我将分四步来带大家研究研究程序的并发计算.第一步是基本的串行程序,然后使用GCD把它并行计算化.如果你想顺着步骤来尝试这些程序的话,可以下载源码.注意,别运行imagegcd2.m,这是个反面教材 ...

  4. 如何使用RDP跳过网络隔离?

    简介 本文我将向大家演示,如何通过RDP跳转盒进入隔离/受保护的网络.下图是我为该场景制作的拓扑图: 简要说明: LAN是一种扁平的工作站和服务器网络. 一些服务器(包括RDP跳转盒)无法与Inter ...

  5. SQL经常使用语法

    一.基础 1.创建数据库 CREATE DATABASE database-name 2.删除数据库 drop database dbname 3.备份sql server --- 创建 备份数据的 ...

  6. [cocos2d-x]怎样降低cocos2d-x游戏的耗电量?

    Cocos2d-x游戏的耗电量一直是个让人头疼的问题,一个简单的三消游戏,玩一会手机就热得发烫,更郁闷的是电池消耗非常快.基本上两个小时就能够把电池耗光. 近期又看到一个帖子.有个老外用cocos2d ...

  7. 编资源bundle时图片文件变成tiff的解决方法

    一般,编写SDK的时候,如果SDK还带了一些资源文件,那么最理想的是将资源文件也打包成为bundle给应用方一起使用.而在编资源bundle时,有时会发现编译好后的图片文件从png转成了tiff,这样 ...

  8. AOP和OOP的区别

    AOP为Aspect Oriented Programming的缩写,意为:面向切面编程,通过预编译方式和运行期动态代理实现程序功能的统一维护的一种技术. AOP与OOP是面向不同领域的两种设计思想. ...

  9. xcode编译 debug版或release 版

    编译debug版本或release 版本 在Run和Stop按钮的右边有一个工程名 点击工程名,选择Manage Schemes 选择Edit... 左侧选择Run ProjectName.app 右 ...

  10. Ajax的简单实现(Json)

    之前写的是一般的Ajax if (request.status === 200) { document.getElementById("createResult").innerHT ...