【BZOJ1036】[ZJOI2008]树的统计Count

来源:互联网 发布:华为 java工程师 编辑:程序博客网 时间:2024/05/22 06:12

大致(一句话)题意:树上单点修改权值+查询两点路径间权值最大值和权值和。

树链剖分模板题。。。

#include <iostream>#include <cstdio>#include <cmath>#include <algorithm>#define N 30009using namespace std;int n,m,number=0,cnt=0,first[N],father[N],top[N],dfn[N],size[N],Mson[N],sum[N*4],Max[N*4],deep[N];struct edge{int to,next;void add(int x,int y){to=y,next=first[x],first[x]=number;}}e[2*N];void dfs1(int x){size[x]=1;deep[x]=deep[father[x]]+1;for (int i=first[x];i;i=e[i].next)if (e[i].to!=father[x]){father[e[i].to]=x;dfs1(e[i].to);size[x]+=size[e[i].to];if (size[e[i].to]>size[Mson[x]])Mson[x]=e[i].to;}}void dfs2(int x,int y){dfn[x]=++cnt;top[x]=y;if (Mson[x]) dfs2(Mson[x],y);for (int i=first[x];i;i=e[i].next)if (e[i].to!=father[x]&&e[i].to!=Mson[x])dfs2(e[i].to,e[i].to);}void ins(int l,int r,int now,int x,int k){if (l==r){sum[k]=x;Max[k]=x;return;}int mid=l+r>>1;if (mid>=now)ins(l,mid,now,x,k<<1);elseins(mid+1,r,now,x,k<<1|1);sum[k]=sum[k<<1]+sum[k<<1|1];Max[k]=max(Max[k<<1],Max[k<<1|1]);}int qry_max(int l,int r,int L,int R,int k){if (L<=l&&R>=r) return Max[k];int mid=l+r>>1;int ans=-126498716;if (L<=mid) ans=max(ans,qry_max(l,mid,L,R,k<<1));if (R>mid) ans=max(ans,qry_max(mid+1,r,L,R,k<<1|1));return ans;}int qry_sum(int l,int r,int L,int R,int k){if (L<=l&&R>=r) return sum[k];int mid=l+r>>1;int ans=0;if (L<=mid) ans+=qry_sum(l,mid,L,R,k<<1);if (R>mid) ans+=qry_sum(mid+1,r,L,R,k<<1|1);return ans;}int qry(int x,int y,int pd){int ans;if (pd) ans=0;else ans=-126498716;for (;top[x]!=top[y];x=father[top[x]]){if (deep[top[x]]<deep[top[y]]) swap(x,y);if (pd) ans+=qry_sum(1,n,dfn[top[x]],dfn[x],1);else ans=max(ans,qry_max(1,n,dfn[top[x]],dfn[x],1));}if (dfn[y]>dfn[x]) swap(x,y);if (pd) ans+=qry_sum(1,n,dfn[y],dfn[x],1);else ans=max(ans,qry_max(1,n,dfn[y],dfn[x],1));return ans;}int main(){scanf("%d",&n);for (int i=1;i<=n-1;i++){int x,y;scanf("%d%d",&x,&y);e[++number].add(x,y);e[++number].add(y,x);}deep[0]=0;father[1]=0;dfs1(1);dfs2(1,1);for (int i=1;i<=n;i++){int x;scanf("%d",&x);ins(1,n,dfn[i],x,1);}scanf("%d",&m);for (int i=1;i<=m;i++){char ch[10];int x,y;scanf("%s%d%d",ch+1,&x,&y);if (ch[1]=='C') ins(1,n,dfn[x],y,1);else if (ch[2]=='M') printf("%d\n",qry(x,y,0));else printf("%d\n",qry(x,y,1));}return 0;}


                                             
0 0
原创粉丝点击