【codevs2460】【BZOJ1036】树的统计count,第一次的树链剖分
2016-03-16 21:05
369 查看
传送门1
传送门2
写在前面:昨天一个小时能A三道题,今天三个小时A一道题
思路:比较裸的树链剖分,只不过是把边权值变成了点权值,开一个数组记录边和点的关系
注意:
1.比较最大值时ans设为-∞,不要设成0!
2.据本人经验,一个结构体有助于身体健康,两个就不行了……
代码:
传送门2
写在前面:昨天一个小时能A三道题,今天三个小时A一道题
思路:比较裸的树链剖分,只不过是把边权值变成了点权值,开一个数组记录边和点的关系
注意:
1.比较最大值时ans设为-∞,不要设成0!
2.据本人经验,一个结构体有助于身体健康,两个就不行了……
代码:
#include<bits/stdc++.h> #define mul(x) (x<<1) #define Minn -0x7fffffff using namespace std; int n,q,tot,x,y,cnt; int first[30010],pre[30010]; char ch[10]; struct point { int top,siz,dep,fa,son,w,hash; }a[30010]; struct os { int u,v,next; }e[60010]; struct node { int sum,maxn; }tree[120010]; void add(int x,int y) { e[++tot].u=x; e[tot].v=y; e[tot].next=first[x]; first[x]=tot; } void dfs1(int now) { a[now].siz=1; for (int i=first[now];i;i=e[i].next) if (e[i].v!=a[now].fa) { a[e[i].v].fa=now; a[e[i].v].dep=a[now].dep+1; dfs1(e[i].v); if (a[e[i].v].siz>a[a[now].son].siz) a[now].son=e[i].v; a[now].siz+=a[e[i].v].siz; } } void dfs2(int now,int tp) { a[now].hash=++cnt; a[now].top=tp; pre[cnt]=now; if (a[now].son) dfs2(a[now].son,tp); for (int i=first[now];i;i=e[i].next) if (e[i].v!=a[now].son&&e[i].v!=a[now].fa) dfs2(e[i].v,e[i].v); } void build(int now,int begin,int end) { if (begin==end) {tree[now].sum=tree[now].maxn=a[pre[begin]].w;return;} int mid=(begin+end)>>1; build(mul(now),begin,mid); build(1+mul(now),mid+1,end); tree[now].maxn=max(tree[mul(now)].maxn,tree[1+mul(now)].maxn); tree[now].sum=tree[mul(now)].sum+tree[1+mul(now)].sum; } void update(int now,int begin,int end,int pos,int num) { if (begin==end) {tree[now].sum=tree[now].maxn=num;return;} int mid=(begin+end)>>1; if (pos<=mid) update(mul(now),begin,mid,pos,num); else update(1+mul(now),mid+1,end,pos,num); tree[now].maxn=max(tree[mul(now)].maxn,tree[1+mul(now)].maxn); tree[now].sum=tree[mul(now)].sum+tree[1+mul(now)].sum; } int get_max(int now,int begin,int end,int l,int r) { if (l<=begin&&end<=r) return tree[now].maxn; int mid=(begin+end)>>1,ans=Minn; if (l<=mid) ans=max(ans,get_max(mul(now),begin,mid,l,r)); if (r>mid) ans=max(ans,get_max(mul(now)+1,mid+1,end,l,r)); return ans; } int get_sum(int now,int begin,int end,int l,int r) { if (l<=begin&&end<=r) return tree[now].sum; int mid=(begin+end)>>1,ans=0; if (l<=mid) ans+=get_sum(mul(now),begin,mid,l,r); if (r>mid) ans+=get_sum(mul(now)+1,mid+1,end,l,r); return ans; } int solve1(int l,int r) { int ans=Minn,f1=a[l].top,f2=a[r].top; while (f1!=f2) { if (a[f1].dep<a[f2].dep) swap(f1,f2),swap(l,r); ans=max(ans,get_max(1,1,cnt,a[f1].hash,a[l].hash)); l=a[f1].fa;f1=a[l].top; } if (a[l].dep>a[r].dep) swap(l,r); return max(ans,get_max(1,1,cnt,a[l].hash,a[r].hash)); } int solve2(int l,int r) { int ans=0,f1=a[l].top,f2=a[r].top; while (f1!=f2) { if (a[f1].dep<a[f2].dep) swap(f1,f2),swap(l,r); ans+=get_sum(1,1,cnt,a[f1].hash,a[l].hash); l=a[f1].fa;f1=a[l].top; } if (a[l].dep>a[r].dep) swap(l,r); return ans+get_sum(1,1,cnt,a[l].hash,a[r].hash); } main() { scanf("%d",&n); for (int i=1;i<n;i++) scanf("%d%d",&x,&y), add(x,y), add(y,x); for (int i=1;i<=n;i++) scanf("%d",&a[i].w); dfs1(1); dfs2(1,1); build(1,1,cnt); scanf("%d",&q); while (q--) { scanf("%s",ch); scanf("%d%d",&x,&y); if (ch[0]=='C') update(1,1,cnt,a[x].hash,y); else { if (ch[1]=='M') printf("%d\n",solve1(x,y)); else printf("%d\n",solve2(x,y)); } } }
相关文章推荐
- 自定义标题栏的问题
- JAVA中的UDP通信(多线程)
- 使用ubuntu作为web开发环境的一些感受
- 剑指offer 栈的压入弹出 顺序
- linux正则表达式
- Hadoop学习笔记系列文章导航
- 22.leetcode题目206: Reverse Linked List
- XCode中遇到not available in automatic reference counting mode 报错
- Http Response Code[整理]
- 动态规划
- Bootstr 导航
- 牛顿法和线搜索&信任域
- 剑指offer 二叉搜索树后续遍历序列 判断
- lightoj 1213 - Fantasy of a Summation 【数学计数】
- Uva 11395 Sigma Function (因子和)
- 胜利大逃亡(续)
- HDU 2412 Party at Hali-Bula(树状DP)
- Android设计模式之23种设计模式一览
- 杨辉三角
- AngularJS 简介