P3178 [HAOI2015]树上操作 树链剖分
这个题就是一道树链剖分的裸题,但是需要有一个魔性操作___编号数组需要开longlong!!!震惊!真的神奇.
题干:
题目描述 有一棵点数为 N 的树,以点 为根,且树点有边权。然后有 M 个操作,分为三种:操作 :把某个节点 x 的点权增加 a 。操作 :把某个节点 x 为根的子树中所有点的点权都增加 a 。操作 :询问某个节点 x 到根的路径中所有点的点权和。
输入输出格式
输入格式: 第一行包含两个整数 N, M 。表示点数和操作数。接下来一行 N 个整数,表示树中节点的初始权值。接下来 N- 行每行两个正整数 from, to , 表示该树中存在一条边 (from, to) 。再接下来 M 行,每行分别表示一次操作。其中第一个数表示该操作的种类( - ) ,之后接这个操作的参数( x 或者 x a ) 。
输出格式:
对于每个询问操作,输出该询问的答案。答案之间用换行隔开。
输入输出样例
输入样例#: 复制 输出样例#: 复制 说明
对于 % 的数据, N,M<= ,且所有输入数据的绝对值都不
会超过 ^ 。
代码:
#include<iostream>
#include<cstdio>
#include<cmath>
#include<ctime>
#include<queue>
#include<algorithm>
#include<cstring>
using namespace std;
#define duke(i,a,n) for(int i = a;i <= n;i++)
#define lv(i,a,n) for(int i = a;i >= n;i--)
#define clean(a) memset(a,0,sizeof(a))
const int INF = << ;
typedef long long ll;
typedef double db;
template <class T>
void read(T &x)
{
char c;
bool op = ;
while(c = getchar(), c < '' || c > '')
if(c == '-') op = ;
x = c - '';
while(c = getchar(), c >= '' && c <= '')
x = x * + c - '';
if(op) x = -x;
}
template <class T>
void write(T x)
{
if(x < ) putchar('-'), x = -x;
if(x >= ) write(x / );
putchar('' + x % );
}
const int N = ;
struct node
{
ll l,r;
int nxt;
}a[N];
int len = ,lst[N];
void add(ll x,ll y)
{
a[++len].l = x;
a[len].r = y;
a[len].nxt = lst[x];
lst[x] = len;
}
ll n,m;
ll tree[N << ],lazy[N << ];
ll siz[N],son[N],cnt = ,id[N];
ll A[N];
ll top[N],f[N],rk[N],dep[N];
int vis[N];
void dfs1(ll u,ll fa,ll depth)
{
f[u] = fa;
siz[u] = ;
dep[u] = depth;
for(int k = lst[u];k;k = a[k].nxt)
{
ll y = a[k].r;
if(y == fa) continue;
dfs1(y,u,depth + );
siz[u] += siz[y];
if(!son[u] || siz[son[u]] < siz[y])
son[u] = y;
}
}
void dfs2(ll u,ll t)
{
vis[u] = ;
top[u] = t;
id[u] = ++cnt;
rk[cnt] = u;
if(!son[u]) return;
dfs2(son[u],t);
for(int k = lst[u];k;k = a[k].nxt)
{
ll y = a[k].r;
if(y == son[u] || y == f[u] || vis[y] == )
continue;
dfs2(y,y);
}
}
void build(ll o,ll l,ll r)
{
if(l == r)
{
tree[o] = A[rk[l]];
return;
}
ll mid = (l + r) >> ;
build(o << ,l,mid);
build(o << | ,mid + ,r);
tree[o] = tree[o << ] + tree[o << | ];
}
void push_down(ll o,ll l,ll r)
{
if(lazy[o] != )
{
ll mid = (l + r) >> ;
tree[o << ] += (ll)(mid - l + ) * lazy[o];
tree[o << | ] += (ll)(r - mid) * lazy[o];
lazy[o << ] += lazy[o];
lazy[o << | ] += lazy[o];
lazy[o] = ;
}
}
void sin_change(ll o,ll l,ll r,ll k,ll w)
{
if(l == r)
{
tree[o] += w;
lazy[o] += w;
return;
}
ll mid = (l + r) >> ;
push_down(o,l,r);
if(mid >= k)
sin_change(o << ,l,mid,k,w);
else
sin_change(o << | ,mid + ,r,k,w);
}
void all_change(ll o,ll l,ll r,ll x,ll y,ll w)
{
if(l == x && r == y)
{
tree[o] += (r - l + ) * w;
lazy[o] += w;
return;
}
push_down(o,l,r);
ll mid = (l + r) >> ;
if(mid >= y)
all_change(o << ,l,mid,x,y,w);
else if(mid < x)
all_change(o << | ,mid + ,r,x,y,w);
else
{
all_change(o << ,l,mid,x,mid,w);
all_change(o << | ,mid + ,r,mid + ,y,w);
}
tree[o] = tree[o << ] + tree[o << | ];
}
ll query(ll o,ll l,ll r,ll x,ll y)
{
if(l == x && r == y)
return tree[o];
push_down(o,l,r);
ll mid = (l + r) >> ;
if(mid >= y)
return query(o << ,l,mid,x,y);
else if(mid < x)
return query(o << | ,mid + ,r,x,y);
else
{
ll ans = ;
ans += query(o << ,l,mid,x,mid);
ans += query(o << | ,mid + ,r,mid + ,y);
return ans;
}
}
ll work(int x,int y)
{
ll ans = ;
while(top[x] != top[y])
{
if(dep[top[x]] < dep[top[y]])
swap(x,y);
ll res = query(,,n,id[top[x]],id[x]);
ans += res;
x = f[top[x]];
}
if(dep[x] > dep[y])
swap(x,y);
ans += query(,,n,id[x],id[y]);
return ans;
}
int main()
{
read(n);read(m);
duke(i,,n)
read(A[i]);
duke(i,,n - )
{
ll x,y;
read(x);read(y);
add(x,y);
add(y,x);
}
dfs1(,,);
dfs2(,);
int ok;
build(,,n);
/*duke(i,1,n)
printf("%d ",top[i]);
cout<<endl;*/
/*duke(i,1,n)
printf("%d ",tree[i]);
cout<<endl;*/
duke(i,,m)
{
read(ok);
if(ok == )
{
ll x;ll y;
read(x);read(y);
all_change(,,n,id[x],id[x],y);
}
else if(ok == )
{
ll x;ll y;
read(x);read(y);
all_change(,,n,id[x],id[x] + siz[x] - ,y);
}
else
{
ll x;
read(x);//printf("!!!%d %d\n",id[1],id[x]);
printf("%lld\n",work(,x));
}
/*duke(i,1,n)
printf("%d ",lazy[i]);
cout<<endl;*/
}
return ;
}
/*
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
*/
P3178 [HAOI2015]树上操作 树链剖分的更多相关文章
- bzoj4034[HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 6163 Solved: 2025[Submit][Stat ...
- bzoj 4034: [HAOI2015]树上操作 树链剖分+线段树
4034: [HAOI2015]树上操作 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 4352 Solved: 1387[Submit][Stat ...
- 【BZOJ4034】[HAOI2015]树上操作 树链剖分+线段树
[BZOJ4034][HAOI2015]树上操作 Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 ...
- BZOJ4034 [HAOI2015]树上操作 树链剖分
欢迎访问~原文出处——博客园-zhouzhendong 去博客园看该题解 题目传送门 - BZOJ4034 题意概括 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三 ...
- BZOJ4034[HAOI2015]树上操作——树链剖分+线段树
题目描述 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中所有点的点权都 ...
- bzoj 4034: [HAOI2015]树上操作——树链剖分
Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个 操作,分为三种: 操作 1 :把某个节点 x 的点权增加 a . 操作 2 :把某个节点 x 为根的子树中 ...
- BZOJ 4034[HAOI2015]树上操作(树链剖分)
Description 有一棵点数为 N 的树,以点 1 为根,且树点有边权.然后有 M 个操作,分为三种:操作 1 :把某个节点 x 的点权增加 a .操作 2 :把某个节点 x 为根的子树中所有点 ...
- bzoj4034 [HAOI2015]树上操作——树链剖分
题目:https://www.lydsy.com/JudgeOnline/problem.php?id=4034 树剖裸题: 一定要注意 long long !!! update 的时候别忘了 pus ...
- [HAOI2015]树上操作-树链剖分
#include<bits/stdc++.h> using namespace std; const int maxn = 1e6+5; #define mid ((l+r)>> ...
随机推荐
- Spring Boot 2.0的属性绑定
Spring Boot2.0的属性绑定 原文从Spring boot第一个版本以来,我们可以使用@ConfigurationProperties注解将属性绑定到对象.也可以指定属性的各种不同格式.比如 ...
- kvm--virsh命令行下管理虚拟机
virsh 既有命令行模式,也有交互模式,在命令行直接输入 virsh 就进入交互模式, virsh 后面跟命令参数,则是命令行模式: (1)基础操作 --- 命令行下管理虚拟机 virsh list ...
- list查询棚舍面积的时候,所有棚舍面积的value都是一样的
解决办法 将pickingid在查list之前set到对象中,通过id来匹配查询 具体代码: FarmHouse farmHouse=new FarmHouse(); farmHouse.setPic ...
- java容器(数组和集合)内元素的排序问题
package com.janson.day20180827; import java.util.*; /** * java中容器内对象的排序可以通过Collections.sort()和Arrays ...
- MyBatis 中 resultMap 详解
resultMap 是 Mybatis 最强大的元素之一,它可以将查询到的复杂数据(比如查询到几个表中数据)映射到一个结果集当中.如在实际应用中,有一个表为(用户角色表),通过查询用户表信息展示页面, ...
- Python学习第二阶段Day2,模块time/datetime、random、os、sys、shutil
1.Time. Datetime(常用) UTC时间:为世界标准时间,时区为0的时间 北京时间,UTC+8东八区 import time print(time.time()) # timestamp ...
- linux动态库加载路径修改
1.在 /etc/ld.so.conf 文件中添加搜索路径,重启或者 ldconfig 生效: 2.在 /etc/ld.so.conf.d 目录下添加 *.conf 文件,其中可以添加搜索路径,重启获 ...
- 50. Spring Boot日志升级篇—log4j【从零开始学Spring Boot】
如果你使用的是spring boot 1.4.0版本的话,那么你可能需要配合以下文章进行学习 90.Spring Boot 1.4 使用log4j错误[从零开始学Spring Boot] Log4j是 ...
- [NOIP2004]FBI树
题目描述 我们可以把由“0”和“1”组成的字符串分为三类:全“0”串称为B串,全“1”串称为I串,既含“0”又含“1”的串则称为F串. FBI树是一种二叉树,它的结点类型也包括F结点,B结点和I结点三 ...
- 【ZJOI2017 Round2练习&BZOJ4826】D1T2 sf(主席树,单调栈)
题意: 思路:From http://blog.csdn.net/neither_nor/article/details/70211150 对每个点i,单调栈求出左边和右边第一个大于i的位置,记为l[ ...