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)>> ...
随机推荐
- ThinkPHP---TP功能类之公文管理功能
[一]准备工作 (1)创建数据表 表名:sp_doc create table sp_doc( id int(11) not null auto_increment, title varchar(50 ...
- react antD moment
import moment from 'moment' console.log(moment().add(1, 'days').format('YYYY-MM-DD')) //当前时间前一天 cons ...
- canvas练手项目(三)——Canvas中的Text文本
Canvas中的Text文本也是一个知识点~,我们需要掌握一下几个基本的Text操作方法 首先是重要参数textAlign和textBaseline: textAlign left center ri ...
- 诊断:Goldengate OGG-01163 Bad column length
故障现象: OGG- Bad column length () specified . 原因:源端修改了字段长度.虽然源端和目标端的长度已经通过DDL语句修改到一致,在extract进程未重启的情况下 ...
- vue 使用vue-i18n做全局中英文切换
1.vue-i18n安装 npm install vue-i18n --save-dev 2.在main.js文件中引入 import VueI18n from 'vue-i18n'; Vue.use ...
- session--保持登录20分钟,常用与用户登录状态
思路:request 与 session 两个作对比 1. . . 2. 3.
- Linux 安装 JDK 详解
安装 JDK 说明:Linux 系统中安装软件需在 root 用户下进行. (1) 首先下载 jdk-8u131-linux-x64.rpm (2)将用户切换至 root,在 opt 文件夹下新建 s ...
- 截取命令cut命令、awk命令、sed命令
cut命令 截取以制表符tab为分隔符的第一列 cut -f 1test.txt 截取以":"为分隔符的第一列,如果比较规律的文件,可以自己设定分隔符 cut -f 1 -d ': ...
- Linux iostat-监视系统输入输出设备和CPU的使用情况
推荐:更多linux 性能监测与优化 关注:linux命令大全 iostat命令被用于监视系统输入输出设备和CPU的使用情况.它的特点是汇报磁盘活动统计情况,同时也会汇报出CPU使用情况.同vmsta ...
- 2018百度之星资格赛T2 子串查询
[题解] 很容易想到暴力做法:对于每个询问暴力查找区间内的最小字母,统计其出现次数.效率O(N^2),无法通过全部数据. 我们可以换一个思路,设f[i][j]为第i个字母(字母‘A'到’Z'分别对应0 ...