1. 程式人生 > >bzoj 1036 樹的統計Count (樹鏈剖分+線段樹)

bzoj 1036 樹的統計Count (樹鏈剖分+線段樹)

char edge sizeof 節點 dfs 維護 printf tdi get

題目大意:給你一棵樹,每個點都有點權

有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\n",Qmax(x,y)); 151 }else{ 152 scanf("%d%d",&x,&y); 153 printf("%lld\n",Qsum(x,y)); 154 } 155 } 156 return 0; 157 }

bzoj 1036 樹的統計Count (樹鏈剖分+線段樹)