bzoj 1036 [ZJOI2008]树的统计Count 树链剖分模板
1036: [ZJOI2008]树的统计Count
Time Limit: 10 Sec Memory Limit: 162 MBSubmit: 18615 Solved: 7598
[Submit][Status][Discuss]
Description
一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成
一些操作: I. CHANGE u t : 把结点u的权值改为t II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值 I
II. 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
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
1
2
2
10
6
5
6
5
16
-------------------------------------------------------------------------------------------------
树链剖分模板题
看黄学长的博客才会的
个人理解:当你想要维护一棵每个点都有权值的树,让这棵树支持在线修改点权值、求点到点的路径上点权和or最大/小值时,就用树链剖分。
剖分的方法有多种,这里用的轻重链。
其原理就是:先找出这棵树的重链,然后按照轻重链给结点重新编号(一条重链上的点的新编号是连续的),然后再按照新编号将树上的所有结点压入数据结构,这里压入一棵线段树。
后面就的操作就在线段树上进行,将路径尽量往重链上靠。
1 #include<stdio.h> 2 #include<string.h> 3 #include<stdlib.h> 4 #include<iostream> 5 #define maxn 233333 6 #define lson ro<<1 7 #define rson ro<<1|1 8 #define inf 1e9 9 using namespace std; 10 struct node{int to,next;}; 11 struct rode{int l,r,sum,mx;}; 12 node e[maxn]; 13 rode tr[maxn]; 14 int n,v[30010],pos[30010],dep[30010],pre[maxn],cnt,fa[30010],size[30010],sz,bl[30010],mxx,an,m; 15 int read(); 16 void insert(int,int); 17 void build(int,int,int); 18 void pushup(int); 19 void dfs1(int); 20 void dfs2(int,int); 21 void querymx(int,int,int); 22 void querysum(int,int,int); 23 int solvemx(int,int); 24 int solvesum(int,int); 25 void change(int,int,int); 26 int main(){ 27 n=read(); 28 for(int i=1;i<n;i++)insert(read(),read()); 29 for(int i=1;i<=n;i++)v[i]=read(); 30 dfs1(1); 31 dfs2(1,1); 32 build(1,n,1); 33 for(int i=1;i<=n;i++) change(pos[i],v[i],1); 34 m=read(); 35 for(int i=1;i<=m;i++){ 36 char cuan[12]; 37 scanf(" %s",cuan); 38 if(cuan[1]=='H'){ 39 int x=read(),k=read(); 40 change(pos[x],k,1); 41 } 42 else if(cuan[1]=='M') printf("%d\n",solvemx(read(),read())); 43 else printf("%d\n",solvesum(read(),read())); 44 } 45 return 0; 46 } 47 int read(){ 48 int ans=0,f=1;char c=getchar(); 49 while('0'>c||c>'9'){if(c=='-')f=-1;c=getchar();} 50 while('0'<=c&&c<='9')ans=ans*10+c-48,c=getchar();return ans*f; 51 } 52 void insert(int x,int y){ 53 e[++cnt].to=y;e[cnt].next=pre[x];pre[x]=cnt; 54 e[++cnt].to=x;e[cnt].next=pre[y];pre[y]=cnt; 55 } 56 void build(int l,int r,int ro){ 57 tr[ro].l=l;tr[ro].r=r; 58 if(l==r) return; 59 int mid=(l+r)>>1; 60 build(l,mid,lson);build(mid+1,r,rson); 61 } 62 void pushup(int ro){ 63 tr[ro].sum=tr[lson].sum+tr[rson].sum; 64 tr[ro].mx=max(tr[lson].mx,tr[rson].mx); 65 } 66 void dfs1(int x){ 67 size[x]=1; 68 for(int i=pre[x];i;i=e[i].next){ 69 int to=e[i].to; 70 if(fa[x]==to)continue; 71 fa[to]=x; 72 dep[to]=dep[x]+1; 73 dfs1(to); 74 size[x]+=size[to]; 75 } 76 } 77 void dfs2(int x,int chain){ 78 int k=0; 79 pos[x]=++sz; 80 bl[x]=chain; 81 for(int i=pre[x];i;i=e[i].next) 82 if(dep[e[i].to]>dep[x]&&size[k]<size[e[i].to]) 83 k=e[i].to; 84 if(k==0)return; 85 dfs2(k,chain); 86 for(int i=pre[x];i;i=e[i].next) 87 if(dep[e[i].to]>dep[x]&&k!=e[i].to) 88 dfs2(e[i].to,e[i].to); 89 } 90 void change(int x,int k,int ro){ 91 if(tr[ro].r==tr[ro].l){ 92 tr[ro].sum=tr[ro].mx=k; 93 return; 94 } 95 int mid=(tr[ro].r+tr[ro].l)>>1; 96 if(x<=mid) change(x,k,lson); 97 else change(x,k,rson); 98 pushup(ro); 99 } 100 void querymx(int l,int r,int ro){ 101 if(l<=tr[ro].l&&tr[ro].r<=r){ 102 mxx=max(mxx,tr[ro].mx); 103 return; 104 } 105 int mid=(tr[ro].l+tr[ro].r)>>1; 106 if(l<=mid) querymx(l,r,lson); 107 if(r>mid) querymx(l,r,rson); 108 } 109 void querysum(int l,int r,int ro){ 110 if(l<=tr[ro].l&&tr[ro].r<=r){ 111 an+=tr[ro].sum; 112 return; 113 } 114 int mid=(tr[ro].l+tr[ro].r)>>1; 115 if(l<=mid) querysum(l,r,lson); 116 if(r>mid) querysum(l,r,rson); 117 } 118 int solvemx(int x,int y){ 119 int mxs=-inf; 120 while(bl[x]!=bl[y]){ 121 if(dep[bl[x]]<dep[bl[y]])swap(x,y); 122 mxx=-inf;querymx(pos[bl[x]],pos[x],1); 123 mxs=max(mxs,mxx); 124 x=fa[bl[x]]; 125 } 126 if(pos[x]>pos[y])swap(x,y); 127 mxx=-inf;querymx(pos[x],pos[y],1); 128 mxs=max(mxs,mxx); 129 return mxs; 130 } 131 int solvesum(int x,int y){ 132 int sum=0; 133 while(bl[x]!=bl[y]){ 134 if(dep[bl[x]]<dep[bl[y]])swap(x,y); 135 an=0;querysum(pos[bl[x]],pos[x],1); 136 sum+=an; 137 x=fa[bl[x]]; 138 } 139 if(pos[x]>pos[y])swap(x,y); 140 an=0;querysum(pos[x],pos[y],1); 141 sum+=an; 142 return sum; 143 }