【BZOJ 4034】【HAOI 2015】树上操作
来源:互联网 发布:一剪梅网络翻唱 编辑:程序博客网 时间:2024/06/06 09:32
BZOJ 4034
题意
给你一棵树和边权,然后有若干个操作,操作分为三种:
操作 1:把某个节点x的点权增加a;
操作 2:把某个节点x为根的子树中所有点的点权都增加a;
操作 3:询问某个节点x到根的路径中所有点的点权和。
样例输入
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
样例输出
6
9
13
SOL
其实这题的核心在于“以x为根的子树具有什么性质”。
还好以前做过这样的题目,所以我知道同一棵子树的dfs序是连续的。转换到树链剖分上来说就是这些节点是一段连续的区间。
那么显然树剖啊!裸题不解释。
完整代码
#include<cmath>#include<cstdio>#include<vector>#include<cstring>#include<iomanip>#include<stdlib.h>#include<iostream>#include<algorithm>#define ll long long#define inf 1000000000#define mod 1000000007#define N 300005using namespace std;struct tree1{ int x,y; void read(){scanf("%d%d",&x,&y);}} e[N];struct tree2 {int len,siz; ll sum;} tree[N*4];vector<int> v[N];int dep[N],siz[N],fa[N],id[N],son[N],val[N],top[N];int T,num,i,n,x,y,q,opt,delta,st,ed;ll lazy[N*4],h[N];void dfs1(int x,int ftr,int d){ dep[x] = d; siz[x] = 1; son[x] = 0; fa[x] = ftr; for (int i = 0;i < v[x].size(); i++) { int nxt = v[x][i]; if (nxt == ftr) continue; dfs1(nxt,x,d+1); siz[x] += siz[nxt]; if (siz[nxt] > siz[son[x]]) son[x] = nxt; }}void dfs2(int x,int tp){ top[x] = tp; id[x] = ++num; if (son[x] > 0) dfs2(son[x],tp); for (int i = 0;i < v[x].size(); i++) { int nxt = v[x][i]; if (nxt == fa[x] || nxt == son[x]) continue; dfs2(nxt,nxt); }}void build(int l,int r,int rt){ tree[rt].len = r - l + 1; if (l == r) {tree[rt].sum = val[l]; tree[rt].siz = 1; return;} int mid = (l + r) >> 1; build(l,mid,rt << 1); build(mid+1,r,rt << 1 | 1); tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum; tree[rt].siz = tree[rt<<1].siz + tree[rt<<1|1].siz + 1;}void pushdown(int x){ if (lazy[x] == 0) return; ll t = lazy[x]; lazy[x<<1] += t; lazy[x<<1|1] += t; tree[x<<1].sum += tree[x<<1].len * t; tree[x<<1|1].sum += tree[x<<1|1].len * t; lazy[x] = 0;}void update(int rt,int l,int r,int L,int R,int s){ if (L <= l && r <= R) { lazy[rt] += (ll) s; tree[rt].sum += (ll) s * tree[rt].len; return; } pushdown(rt); int mid = (l + r) >> 1; if (L <= mid) update(rt<<1,l,mid,L,R,s); if (mid < R) update(rt<<1|1,mid+1,r,L,R,s); tree[rt].sum = tree[rt<<1].sum + tree[rt<<1|1].sum;}ll query(int rt,int l,int r,int L,int R){ pushdown(rt); if (L <= l && r <= R) return tree[rt].sum; int mid = (l + r) >> 1; ll res = 0; if (L <= mid) res += query(rt<<1,l,mid,L,R); if (mid < R) res += query(rt<<1|1,mid+1,r,L,R); return res;}ll link(int u,int v){ int top1 = top[u]; int top2 = top[v]; ll res = 0; while (top1 != top2) { if (dep[top1] < dep[top2]) {swap(top1,top2); swap(u,v);} res += query(1,1,n,id[top1],id[u]); u = fa[top1]; top1 = top[u]; } if (dep[u] > dep[v]) swap(u,v); res += query(1,1,n,id[u],id[v]); return res;}int main(){ scanf("%d%d",&n,&q); for (i = 1;i <= n; i++) scanf("%d",&h[i]); for (i = 1;i < n; i++) { e[i].read(); v[e[i].x].push_back(e[i].y); v[e[i].y].push_back(e[i].x); } num = 0; dfs1(1,0,1); dfs2(1,1); for (i = 1;i <= n; i++) val[id[i]] = h[i]; build(1,n,1); for (i = 1;i <= q; i++) { scanf("%d",&opt); if (opt == 1 || opt == 2) { scanf("%d%d",&x,&delta); st = id[x]; if (opt == 1) ed = st; else ed = st + siz[x] - 1; update(1,1,n,st,ed,delta); } if (opt == 3) { scanf("%d",&x); ll h = link(x,1); printf("%lld\n",h); } } return 0; }
0 0
- 【BZOJ 4034】【HAOI 2015】树上操作
- 【BZOJ 4034】【HAOI 2015】树上操作
- 【BZOJ 4034】【HAOI 2015】树上操作【树链剖分】
- [BZOJ 4034][HAOI 2015] 树上操作 树链剖分+DFS序
- BZOJ 4034 [HAOI2015]树上操作
- bzoj 4034 [HAOI2015]树上操作
- 【BZOJ 4034】 [HAOI2015]树上操作
- BZOJ 4034: [HAOI2015]树上操作
- BZOJ 4034 树上操作 链剖
- bzoj 4034 [HAOI2015]树上操作
- BZOJ 4034 [HAOI2015]树上操作
- BZOJ 2427 HAOI 2010 软件安装 Tarjan+树上DP
- bzoj 4034: [HAOI2015]树上操作 (树链剖分)
- 【BZOJ】4034 [HAOI2015]树上操作 树链剖分
- BZOJ 4034 [HAOI2015]树上操作 树链剖分
- BZOJ 4034 :[HAOI2015]树上操作 树链剖分裸题
- bzoj 4034 树上操作 树链剖分 解题报告
- 【bzoj 4034】树上操作(树链剖分)
- Struts2(随笔) 17-2-20
- 分布式与集群的区别与联系
- Android热门第三方库
- /etc/oraInst.loc文件的位置
- 后缀数组(不小于k个字符串中的最长子串)
- 【BZOJ 4034】【HAOI 2015】树上操作
- JAVA 8 StreamAPI 和 lambda表达式 总结(一)--lambda表达式
- 对前面信息管理系统的完善
- 【iOS技术文章】iOS Label的几种样式
- 蓝桥杯 算法提高 选择排序
- 哈希表及其实现
- Mac下MonoDeveloper快捷键
- 关于Mac安装MySQL和MySQLWorkbench的初始密码,环境配置问题总结
- JavaSE 学习参考:数组遍历