BZOJ 1036 树的统计Count(树链剖分+线段树)
2015-12-06 12:24
302 查看
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
4
1
2
2
10
6
5
6
5
16
Solution
树上路径问题,首先树链剖分,然后建线段树,线段树中元素存储区间和和区间最大值,那么三种操作就变成了线段树单点更新与区间查询操作了
Code
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 III. QSUM u v: 询问从点u到点v的路径上的节点的权值和 注意:从点u到点v的路径上的节点包括u和v本身
Input
输入的第一行为一个整数n,表示节点的个数。接下来n – 1行,每行2个整数a和b,表示节点a和节点b之间有一条边相连。接下来n行,每行一个整数,第i行的整数wi表示节点i的权值。接下来1行,为一个整数q,表示操作的总数。接下来q行,每行一个操作,以“CHANGE u t”或者“QMAX u v”或者“QSUM u v”的形式给出。 对于100%的数据,保证1<=n<=30000,0<=q<=200000;中途操作中保证每个节点的权值w在-30000到30000之间。
Output
对于每个“QMAX”或者“QSUM”的操作,每行输出一个整数表示要求输出的结果。
Sample Input
4
1 2
2 3
4 1
4 2 1 3
12
QMAX 3 4
QMAX 3 3
QMAX 3 2
QMAX 2 3
QSUM 3 4
QSUM 2 1
CHANGE 1 5
QMAX 3 4
CHANGE 3 6
QMAX 3 4
QMAX 2 4
QSUM 3 4
Sample Output
4
1
2
2
10
6
5
6
5
16
Solution
树上路径问题,首先树链剖分,然后建线段树,线段树中元素存储区间和和区间最大值,那么三种操作就变成了线段树单点更新与区间查询操作了
Code
#include<cstdio> #include<iostream> #include<algorithm> #include<cstring> using namespace std; #define maxn 33333 #define INF 0x3f3f3f3f struct Edge { int to,next; }E[2*maxn]; struct Tree { int left,right,Max,Sum; }T[4*maxn]; int n,q,val[maxn],w[maxn],head[maxn],cnt,idx,size[maxn],fa[maxn],son[maxn],dep[maxn],top[maxn],id[maxn],pos[maxn]; void init() { cnt=idx=0; memset(head,-1,sizeof(head)); dep[1]=fa[1]=size[0]=0; memset(son,0,sizeof(son)); } void add(int u,int v) { E[cnt].to=v; E[cnt].next=head[u]; head[u]=cnt++; } void dfs1(int u) { size[u]=1; for(int i=head[u];~i;i=E[i].next) { int v=E[i].to; if(v!=fa[u]) { fa[v]=u; dep[v]=dep[u]+1; dfs1(v); size[u]+=size[v]; if(size[son[u]]<size[v]) son[u]=v; } } } void dfs2(int u,int topu) { top[u]=topu; id[u]=++idx; pos[idx]=u; if(son[u]) dfs2(son[u],top[u]); for(int i=head[u];~i;i=E[i].next) { int v=E[i].to; if(v!=fa[u]&&v!=son[u]) dfs2(v,v); } } void push_up(int t) { T[t].Max=max(T[2*t].Max,T[2*t+1].Max); T[t].Sum=T[2*t].Sum+T[2*t+1].Sum; } void build(int l,int r,int t) { T[t].left=l; T[t].right=r; T[t].Max=-INF; T[t].Sum=0; if(l==r) { T[t].Max=T[t].Sum=val[pos[l]]; return ; } int mid=(l+r)>>1; build(l,mid,2*t); build(mid+1,r,2*t+1); push_up(t); } void update(int x,int v,int t) { if(T[t].left==x&&T[t].right==x) { T[t].Max=T[t].Sum=v; return ; } if(x<=T[2*t].right) update(x,v,2*t); else update(x,v,2*t+1); push_up(t); } int query_sum(int l,int r,int t) { if(T[t].left==l&&T[t].right==r) return T[t].Sum; if(r<=T[2*t].right) return query_sum(l,r,2*t); else if(l>=T[2*t+1].left) return query_sum(l,r,2*t+1); return query_sum(l,T[2*t].right,2*t)+query_sum(T[2*t+1].left,r,2*t+1); } int query_max(int l,int r,int t) { if(T[t].left==l&&T[t].right==r) return T[t].Max; if(r<=T[2*t].right) return query_max(l,r,2*t); else if(l>=T[2*t+1].left) return query_max(l,r,2*t+1); return max(query_max(l,T[2*t].right,2*t),query_max(T[2*t+1].left,r,2*t+1)); } int QSUM(int u,int v) { int top1=top[u],top2=top[v],ans=0; while(top1!=top2) { if(dep[top1]<dep[top2]) { swap(top1,top2); swap(u,v); } ans+=query_sum(id[top1],id[u],1); u=fa[top1]; top1=top[u]; } if(dep[u]>dep[v]) swap(u,v); ans+=query_sum(id[u],id[v],1); return ans; } int QMAX(int u,int v) { int top1=top[u],top2=top[v],ans=-INF; while(top1!=top2) { if(dep[top1]<dep[top2]) { swap(top1,top2); swap(u,v); } ans=max(ans,query_max(id[top1],id[u],1)); u=fa[top1]; top1=top[u]; } if(dep[u]>dep[v]) swap(u,v); ans=max(ans,query_max(id[u],id[v],1)); return ans; } int main() { while(~scanf("%d",&n)) { init(); int u,v,c;char op[11]; for(int i=1;i<n;i++) { scanf("%d%d",&u,&v); add(u,v),add(v,u); } for(int i=1;i<=n;i++) scanf("%d",&val[i]); dfs1(1); dfs2(1,1); build(1,n,1); scanf("%d",&q); while(q--) { scanf("%s",op); scanf("%d%d",&u,&v); if(op[0]=='C') update(id[u],v,1); else if(op[1]=='S') printf("%d\n",QSUM(u,v)); else printf("%d\n",QMAX(u,v)); } } return 0; }
相关文章推荐
- jforum中对各种servlet对象都进行了封装
- hdu 5592 ZYB's Game 树状数组
- 《利用python进行数据分析》读书笔记--第七章 数据规整化:清理、转换、合并、重塑(一)
- mysql 修改密码,修改加密方式
- Java 注释
- iOS开发-多线程-GDC的基本使用
- hdu 4281 Judges' response 状压DP+TSP ★★★★
- CodeIgniter 框架
- 信息安全系统设计基础第十三周学习总结
- 小谈数据库的Left Outer Join和CTE
- Android应用中图片资源尺寸
- android玩耍(-) adbshell安装
- [LeetCode]Word Break II
- hdu 5591 ZYB's Game 博弈论
- 黑马程序员——OC基础之NSMutableDictionary
- Java之I/O流小结
- 清理SQLServer链接历史记录
- 黑马程序员——OC基础之NSDictionary
- Lowest Common Multiple Plus 解题C++
- Android源码下载