给你n个点,m条边,p次操作。n个点相连后是一棵树。每次操作可以是x 到 y 增加 z,或者减z,或者问当前点的值是多少。

可以将树分成链,每个点在线段树上都有自己的点,然后线段树成段更新一下。

#pragma comment(linker, "/STACK:1024000000,1024000000")
#include<queue>
#include<stack>
#include<cmath>
#include<cstdio>
#include<cstring>
#include<iostream>
#include<algorithm>
#define INF 99999999
#define ll __int64
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1
using namespace std;
const int MAXN = ;
struct node
{
int to;
int v;
int next;
}edge[MAXN*];
int pre[MAXN],ind,top[MAXN],fa[MAXN],son[MAXN],w[MAXN],deq[MAXN],siz[MAXN],fn;
int tree[MAXN<<],mark[MAXN<<];
int n,m,val[MAXN];
void add(int x,int y)
{
edge[ind].to = y;
edge[ind].next = pre[x];
pre[x] = ind++;
}
void dfs1(int rt,int pa,int d)
{
deq[rt] = d;
son[rt] = ;
fa[rt] = pa;
siz[rt] = ;
int i;
for(i=pre[rt]; i!=-; i=edge[i].next){
int t = edge[i].to;
if(t != fa[rt]){
dfs1(t,rt,d+);
siz[rt] += siz[t];
if(siz[son[rt]] < siz[t]){
son[rt] = t;
}
}
}
}
void dfs2(int rt,int tp)
{
w[rt] = ++fn;
top[rt] = tp;
if(son[rt] != )
dfs2(son[rt], tp);
for(int i=pre[rt]; i!=-; i=edge[i].next){
int t = edge[i].to;
if(t != son[rt] && t != fa[rt]){
dfs2(t,t);
}
}
}
void build(int l,int r,int rt)
{
tree[rt] = ;
mark[rt] = ;
if(l == r)
return ;
int m = (l+r)/;
build(lson);
build(rson);
}
void pushdown(int rt)
{
if(mark[rt] != ){
mark[rt<<|] += mark[rt];
mark[rt<<] += mark[rt];
tree[rt<<|] += mark[rt];
tree[rt<<] += mark[rt];
mark[rt] = ;
}
}
void Insert(int p,int v,int l,int r,int rt)
{
if(l == r){
tree[rt] = v;
return ;
}
int m = (l+r)/;
if(m >= p){
Insert(p,v,lson);
}
else Insert(p,v,rson);
}
void updata(int L,int R,int v,int l,int r,int rt)
{
if(L<=l && r<=R){
mark[rt] += v;
tree[rt] += v;
return ;
}
pushdown(rt); int m = (l+r)/;
if(m >= L){
updata(L,R,v,lson);
}
if(m < R){
updata(L,R,v,rson);
}
}
int query(int p,int l,int r,int rt)
{
if(l == r){
return tree[rt];
}
pushdown(rt);
int m = (l+r)/;
if(m >= p){
return query(p,lson);
}
else {
return query(p,rson);
}
}
void updata_all(int x,int y,int z)
{
while(top[x] != top[y])
{
if(deq[top[x]] < deq[top[y]]){
swap(x,y);
}
updata(w[top[x]],w[x],z,,fn,); x = fa[top[x]];
}
if(deq[x] < deq[y]){
swap(x,y);
}
updata(w[y],w[x],z,,fn,);
}
int main()
{
int i,j,p;
while(~scanf("%d%d%d",&n,&m,&p))
{
for(i=; i<=n; i++){
scanf("%d",&val[i]);
}
ind = ;
memset(pre,-,sizeof(pre));
for(i=; i<=m; i++){
int x,y;
scanf("%d%d",&x,&y);
add(x,y);
add(y,x);
}
dfs1(,,);
fn = ;
dfs2(,); build(,n,);
for(i=; i<=n; i++){
Insert(w[i],val[i],,fn,);
}
char s[];
while(p--)
{
scanf("%s",s);
if(s[] == 'I'){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
updata_all(x,y,z);
}
else if(s[] == 'D'){
int x,y,z;
scanf("%d%d%d",&x,&y,&z);
updata_all(x,y,-z);
}
else {
int x;
scanf("%d",&x);
printf("%d\n",query(w[x],,fn,));
}
}
}
}

hdu3966 树链剖分+成段更新的更多相关文章

  1. bzoj2243树链剖分+染色段数

    终于做了一道不是一眼出思路的代码题(⊙o⊙) 之前没有接触过这种关于染色段数的题目(其实上课好像讲过),于是百度了一下(现在思维能力好弱) 实际上每一段有用的信息就是总共有几段和两段各是什么颜色,在开 ...

  2. POJ 2155 Matrix (二维线段树入门,成段更新,单点查询 / 二维树状数组,区间更新,单点查询)

    题意: 有一个n*n的矩阵,初始化全部为0.有2中操作: 1.给一个子矩阵,将这个子矩阵里面所有的0变成1,1变成0:2.询问某点的值 方法一:二维线段树 参考链接: http://blog.csdn ...

  3. HDU1698 Just a Hook 【线段树】+【成段更新】+【lazy标记】

    Just a Hook Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others) Tota ...

  4. [HDOJ4027]Can you answer these queries?(线段树,特殊成段更新,成段查询)

    题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4027 RT,该题要求每次更新是更新所有节点,分别求平方根,查询是求和.昨晚思前想后找有没有一个数学上的 ...

  5. HDU3966(树链剖分)

    题目:Aragorn's Story 题意:给一棵树,并给定各个点权的值,然后有3种操作: I C1 C2 K: 把C1与C2的路径上的所有点权值加上K D C1 C2 K:把C1与C2的路径上的所有 ...

  6. hdu3966 树链剖分点权模板+线段树区间更新/树状数组区间更新单点查询

    点权树的模板题,另外发现树状数组也是可以区间更新的.. 注意在对链进行操作时方向不要搞错 线段树版本 #include<bits/stdc++.h> using namespace std ...

  7. POJ2528 Mayor&#39;s posters 【线段树】+【成段更新】+【离散化】

    Mayor's posters Time Limit: 1000MS   Memory Limit: 65536K Total Submissions: 39795   Accepted: 11552 ...

  8. 树链剖分(单点更新,求区间最值,区间求和Bzoj1036)

    1036: [ZJOI2008]树的统计Count Time Limit: 10 Sec  Memory Limit: 162 MB Submit: 5759  Solved: 2383 [Submi ...

  9. POJ3468 A Simple Problem with Integers 【段树】+【成段更新】

    A Simple Problem with Integers Time Limit: 5000MS   Memory Limit: 131072K Total Submissions: 57666   ...

随机推荐

  1. 从c到c++

    1,stack模板类(头文件为<stack>)需要定义两个参数:元素类型(必要).容器类型(默认为deque), 定义stack对象 stack <string> s 基本操作 ...

  2. Java语法基础(一)----关键字、标识符、常量、变量

    一.关键字: 关键字:被Java语言赋予特定含义的单词.组成关键字的字母全部小写.注:goto和const作为保留字存在,目前并不使用.main并不是关键字. 二.标识符: 标识符:就是给类,接口,方 ...

  3. WWW压缩解压缩

    unity的WWW参考文档:http://game.ceeger.com/Script/WWW/WWW.html 在unity中把资源打包成Assetbundle其实把资源通过 LZMA 压缩成二进制 ...

  4. js原生选项卡(自动播放无缝滚动轮播图)二

    今天分享一下自动播放轮播图,自动播放轮播图是在昨天分享的轮播图的基础上添加了定时器,用定时器控制图片的自动切换,函数中首先封装一个方向的自动播放工能的小函数,这个函数中添加定时器,定时器中可以放向右走 ...

  5. js实现复制功能

    JS 点击复制Copy 1.实现点击按钮,复制文本框中的的内容 1 <script type="text/javascript"> 2 function copyUrl ...

  6. WPF登陆窗口、主窗口切换问题

    代码 MainWindow mwin = new MainWindow(); Application.Current.MainWindow = mwin; this.Close(); mwin.Sho ...

  7. 第二章 rabbitmq在mac上的安装

    下载页: http://www.rabbitmq.com/install-standalone-mac.html 1.下载页面首部的文件(页面下载可能比较慢,使用迅雷下载就好),之后解压到一个合适的路 ...

  8. AD域的安装

    AD域的安装 初始化设置,改计算机名字dcserver,改静态ip,改dns指向自己. dcpromo,执行后自动装了dns.   装完后检查 1,本地用户没了 2,dns指向自己 3,dns记录是否 ...

  9. android Camera 如何判断当前使用的摄像头是前置还是后置

    现在 android 平台的智能手机一般都标配有两颗摄像头.在 Camera 中都存在摄像头切换的功能. 并且有一些功能前后置摄像头上会有所不同.譬如人脸检测,人脸识别,自动对焦,闪光灯等功能, 如果 ...

  10. SpringMVC Controller介绍(转)

    SpringMVC Controller 介绍 一.简介 在SpringMVC 中,控制器Controller 负责处理由DispatcherServlet 分发的请求,它把用户请求的数据经过业务处理 ...