【BZOJ 4034】【HAOI 2015】树上操作
来源:互联网 发布:python append extend 编辑:程序博客网 时间:2024/06/06 06:38
考虑到在dfs序中,以某个节点为根的子树的编号一定是连续的,所以可以用树剖来做。单点修改和查询都是裸的树剖操作,而区间修改只要找到区间大小就行了,dfs的时候记录一下子树大小即可。
貌似吉老司机给出了树状数组的做法,但我不知道怎么查询QAQ
#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】树上操作(树链剖分)
- POJ 3259 Wormholes 最短路径
- Android 顶部悬浮栏 + ViewPager + RecyclerView
- 数据结构-散列
- oracle 远程连接提示 ora-12541错误
- 老男孩OpenStack企业私有云实战培训
- 【BZOJ 4034】【HAOI 2015】树上操作
- ecshop的插入分类sql
- sdut 3260 大数取模
- 运算放大器使用的6个注意事项
- 常用adb命令
- Ubuntu——段错误 核心已转储
- Android 获取屏幕分辨率
- Webpack-源码一,使用require加载并打包模块
- 2017年年初总结