树的统计(树剖)指针版
来源:互联网 发布:acrobat xi mac 破解 编辑:程序博客网 时间:2024/06/16 20:04
题目>>http://codevs.cn/problem/2460/
#include<iostream>#include<cstdio>#include<algorithm>#include<cstring>using namespace std;const int MAXN = 1e6 + 5;typedef long long ll;ll n,a,b,num[MAXN],q,firs[MAXN],nex[MAXN],cnt = 0;char s[15];struct zt{ ll f,t;}road[MAXN];void build(ll f,ll t){ road[++cnt] = (zt){f,t}; nex[cnt] = firs[f]; firs[f] = cnt;} ll fa[MAXN],son[MAXN],sz[MAXN],deep[MAXN];void dfs1(ll x,ll f){ fa[x] = f; deep[x] = deep[f] + 1; sz[x] = 1; for(int i = firs[x];i != -1;i = nex[i]) { ll v = road[i].t; if(v != f) { dfs1(v,x); sz[x] += sz[v]; if(!son[x]||sz[v] > sz[son[x]]) son[x] = v; } }}ll intu[MAXN],top[MAXN],tot = 0;void dfs2(ll x,ll topx){ top[x] = topx; intu[x] = ++tot; if(!son[x]) return; dfs2(son[x],topx); for(int i = firs[x];i != -1;i = nex[i]) { int v = road[i].t; if(v != fa[x]&&v != son[x]) dfs2(v,v); } }struct dd{ ll sum,maxn; dd *lift,*right;}tree[MAXN];ll cc = 0;void hs(dd *root){ root->sum = root->lift->sum + root->right->sum; root->maxn = max(root->lift->maxn,root->right->maxn);}void build_tree(dd *root,ll l,ll r){ root->sum = 0;root->maxn = 0; if(l == r) return; ll mid = l + r >>1; root->right = &tree[++cc]; root->lift = &tree[++cc]; build_tree(root->lift,l,mid); build_tree(root->right,mid + 1,r); hs(root);}void change(dd *root,ll l,ll r,ll q,ll x){ if(l == r) { root->sum = root->maxn = x; return; } ll mid = l + r >> 1; if(q <= mid) change(root->lift,l,mid,q,x); else change(root->right,mid + 1,r,q,x); hs(root);}ll ask_sum(dd *root,ll l,ll r,ll ql,ll qr){ if(l >= ql&&qr >= r) return root->sum; ll mid = l + r >> 1,ans = 0; if(ql <= mid) ans += ask_sum(root->lift,l,mid,ql,qr); if(qr > mid) ans += ask_sum(root->right,mid + 1,r,ql,qr); return ans;}ll find_sum(ll x,ll y){ ll xt = top[x],yt = top[y],ans = 0; while(xt != yt) { if(deep[xt] < deep[yt]) swap(xt,yt),swap(x,y); ans += ask_sum(tree,1,n,intu[xt],intu[x]); x = fa[xt];xt = top[x]; } if(deep[x] > deep[y]) swap(x,y); ans += ask_sum(tree,1,n,intu[x],intu[y]); return ans;}ll ask_max(dd *root,ll l,ll r,ll ql,ll qr){ if(l >= ql&&qr >= r) return root->maxn; ll mid = l + r >> 1,ans = -1e6; if(ql <= mid) ans = max(ask_max(root->lift,l,mid,ql,qr),ans); if(qr > mid) ans = max(ask_max(root->right,mid + 1,r,ql,qr),ans); return ans;}ll find_max(ll x,ll y){ ll xt = top[x],yt = top[y],ans = -1e6; while(xt != yt) { if(deep[xt] < deep[yt]) swap(xt,yt),swap(x,y); ans = max(ask_max(tree,1,n,intu[xt],intu[x]),ans); x = fa[xt];xt = top[x]; } if(deep[x] > deep[y]) swap(x,y); ans = max(ask_max(tree,1,n,intu[x],intu[y]),ans); return ans;}int main(){ scanf("%lld",&n); for(int i = 1;i <= n;i ++) firs[i] = -1; for(int i = 1;i < n;i ++) { scanf("%lld%lld",&a,&b); build(a,b); build(b,a); } dfs1(1,0); dfs2(1,1); build_tree(tree,1,n); for(int i = 1;i <= n; i++) { scanf("%lld",&a); change(tree,1,n,intu[i],a); } scanf("%lld",&q); for(int i = 1;i <= q;i ++) { scanf("%s%lld%lld",s,&a,&b); if(s[0] == 'C') change(tree,1,n,intu[a],b),num[a] = b; else if(s[1] == 'M') cout<<find_max(a,b)<<'\n'; else cout<<find_sum(a,b)<<'\n'; }}
阅读全文
0 0
- 树的统计(树剖)指针版
- 统计素数的和(指针法)
- 统计字符串中单词的个数(指针)
- 统计输入中C语言关键字的出现次数 指针实现版本 (《C程序设计语言》 第二版)
- 第十六周项目二用指针玩字符串任务四:统计句子中单词的个数(用指针作形参)
- 第十六周项目2-用指针玩字符串(任务四:统计单词的个数)
- 第十六周项目2-用指针玩字符串(任务四:统计单词的个数)
- C和指针之字符串编程练习11(统计一串字符包含the的个数)
- 20140723 【字典树 - 前缀树,指针版】 HDOJ 1251 统计难题
- 指针统计字符串长度
- HYSBZ - 1036 树的统计Count(树剖)
- [c++的运用]-使用迭代器,vector指针统计分数---ShinePans
- codevs 2460 [ZJOI] 树的统计 树剖
- C/C++复习:统计字符串种类(指针)
- 第十六周项目二——用指针玩字符串(4.统计句子str中单词的个数)
- 统计难题(字典树的应用)
- 【ZJOI2008】树的统计(树链剖分)
- bzoj1036 [ZJOI2008]树的统计(树链剖分)
- argparse模块
- wx.openLocation调取失败
- java执行Linux bash命令
- linux命令之free
- H5+CSS3实现奥运5环
- 树的统计(树剖)指针版
- node.js实现跨域AJAX post
- 半平面交,求解多边形内核
- 微信最新的系统默认emoji表情集
- 在EmEditor上编译并运行JAVA
- date命令使用总结
- KMP——理论知识
- AngularsJS循环
- java Hashmap