bzoj 1036 树的统计Count (树链剖分+线段树)

Posted guapisolo

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了bzoj 1036 树的统计Count (树链剖分+线段树)相关的知识,希望对你有一定的参考价值。

题目大意:给你一棵树,每个点都有点权

有3种操作,修改某节点的权值,求树链上节点的权值的最大值,求树链上节点的权值和

树剖裸题,搜一个树链剖分序,用线段树维护一下即可,总时间技术分享图片

  1 #include <cstdio>
  2 #include <algorithm>
  3 #include <cstring>
  4 #include <queue>
  5 #define inf 0x3f3f3f3f
  6 #define ll long long 
  7 #define N 30100
  8 using namespace std;
  9 
 10 char str[10];
 11 int n,num,cte;
 12 ll a[N],sum[N<<2],ma[N<<2];
 13 int dep[N],head[N],son[N],sz[N],que[N],pos[N],tp[N],fa[N];
 14 struct Chain{
 15     int up,dw;
 16     Chain(int up,int dw):up(up),dw(dw){}
 17 };
 18 struct EDGE{
 19     int to,nxt;
 20 }edge[N<<1];
 21 void edge_add(int u,int v)
 22 {
 23     cte++;
 24     edge[cte].to = v;
 25     edge[cte].nxt=head[u];
 26     head[u]=cte;
 27 }
 28 void dfs1(int x,int pre)
 29 {
 30     for(int j=head[x];j!=-1;j=edge[j].nxt)
 31     {
 32         int v=edge[j].to;
 33         if(v==pre) continue;
 34         dep[v]=dep[x]+1;
 35         fa[v]=x;
 36         dfs1(v,x);
 37         son[x]=(sz[v]>sz[son[x]])?v:son[x];
 38         sz[x]+=sz[v];
 39     }
 40     sz[x]++;
 41 }
 42 void dfs2(int x)
 43 {
 44     que[++num]=x,pos[x]=num;
 45     if(son[x]) tp[son[x]]=tp[x],dfs2(son[x]);
 46     for(int j=head[x];j!=-1;j=edge[j].nxt)
 47     {
 48         int v=edge[j].to;
 49         if(v==fa[x]||v==son[x]) continue;
 50         tp[v]=v,dfs2(v);
 51     }
 52 }
 53 void pushup(int rt){
 54     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
 55     ma[rt]=max(ma[rt<<1],ma[rt<<1|1]);
 56 }
 57 void build(int l,int r,int rt)
 58 {
 59     if(l==r){sum[rt]=ma[rt]=a[que[l]];return;}
 60     int mid=(l+r)>>1;
 61     build(l,mid,rt<<1);
 62     build(mid+1,r,rt<<1|1);
 63     pushup(rt);
 64 }
 65 void update(int x,int l,int r,int rt,ll w)
 66 {
 67     if(l==r){sum[rt]=ma[rt]=a[que[l]];return;}
 68     int mid=(l+r)>>1;
 69     if(x<=mid) update(x,l,mid,rt<<1,w);
 70     else  update(x,mid+1,r,rt<<1|1,w);
 71     pushup(rt);
 72 }
 73 ll qmax1(int L,int R,int l,int r,int rt)
 74 {
 75     if(L<=l&&r<=R) return ma[rt];
 76     int mid=(l+r)>>1;ll ans=-inf;
 77     if(L<=mid) ans=max(ans,qmax1(L,R,l,mid,rt<<1));
 78     if(R>mid) ans=max(ans,qmax1(L,R,mid+1,r,rt<<1|1));
 79     return ans;
 80 }
 81 ll qsum1(int L,int R,int l,int r,int rt)
 82 {
 83     if(L<=l&&r<=R) return sum[rt];
 84     int mid=(l+r)>>1;ll ans=0;
 85     if(L<=mid) ans+=qsum1(L,R,l,mid,rt<<1);
 86     if(R>mid) ans+=qsum1(L,R,mid+1,r,rt<<1|1);
 87     return ans;
 88 }
 89 int LCA(int x,int y)
 90 {
 91     while(tp[x]!=tp[y]){
 92         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
 93         x=fa[tp[x]];
 94     }return dep[x]<dep[y]?x:y;
 95 }
 96 queue<Chain>q;
 97 ll Qmax(int x,int y)
 98 {
 99     while(tp[x]!=tp[y]){
100         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
101         q.push(Chain(tp[x],x));
102         x=fa[tp[x]];    
103     } if(dep[x]<dep[y]) swap(x,y);
104     q.push(Chain(y,x));ll ans=-inf;
105     while(!q.empty()){
106         Chain k=q.front();q.pop();
107         ans=max(ans,qmax1(pos[k.up],pos[k.dw],1,n,1));
108     }return ans;
109 }
110 ll Qsum(int x,int y)
111 {
112     while(tp[x]!=tp[y]){
113         if(dep[tp[x]]<dep[tp[y]]) swap(x,y);
114         q.push(Chain(tp[x],x));
115         x=fa[tp[x]];
116     } if(dep[x]<dep[y]) swap(x,y);
117     q.push(Chain(y,x));ll ans=0;
118     while(!q.empty()){
119         Chain k=q.front();q.pop();
120         ans+=qsum1(pos[k.up],pos[k.dw],1,n,1);
121     }return ans;
122 }
123 
124 int main()
125 {
126     //freopen("data.in","r",stdin);
127     scanf("%d",&n);
128     int x,y;ll z;
129     memset(head,-1,sizeof(head));
130     for(int i=1;i<n;i++)
131     {
132         scanf("%d%d",&x,&y);
133         edge_add(x,y);
134         edge_add(y,x);
135     } 
136     for(int i=1;i<=n;i++) scanf("%lld",&a[i]);
137     dep[1]=1,dfs1(1,-1);
138     tp[1]=1,dfs2(1);
139     build(1,n,1);
140     int q=0;
141     scanf("%d",&q);
142     for(int i=1;i<=q;i++)
143     {
144         scanf("%s",str);
145         if(str[1]==H){
146             scanf("%d%lld",&x,&z),a[x]=z;
147             update(pos[x],1,n,1,z);
148         }else if(str[1]==M){
149             scanf("%d%d",&x,&y);
150             printf("%lld
",Qmax(x,y));
151         }else{
152             scanf("%d%d",&x,&y);
153             printf("%lld
",Qsum(x,y));
154         }
155     }
156     return 0;
157 }

 

以上是关于bzoj 1036 树的统计Count (树链剖分+线段树)的主要内容,如果未能解决你的问题,请参考以下文章

BZOJ1036: [ZJOI2008]树的统计Count - 树链剖分 -

BZOJ 1036: [ZJOI2008]树的统计Count [树链剖分]

bzoj 1036 树的统计Count (树链剖分+线段树)

bzoj 1036 [ZJOI2008]树的统计Count 树链剖分模板

bzoj 1036: [ZJOI2008]树的统计Count (树链剖分)

[BZOJ1036][ZJOI2008]树的统计Count(树链剖分)