BZOJ1036: [ZJOI2008]树的统计Count - 树链剖分 -
1036: [ZJOI2008]树的统计Count
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
HINT
Source
Solution
剖一下,线段树维护一下。
模板题……
Code
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<map> 2 #include<set> 3 #include<cmath> 4 #include<ctime> 5 #include<deque> 6 #include<queue> 7 #include<stack> 8 #include<cstdio> 9 #include<vector> 10 #include<climits> 11 #include<cstring> 12 #include<cstdlib> 13 #include<iostream> 14 #include<algorithm> 15 using namespace std; 16 typedef long long LL; 17 const int Maxn=1000000+1; 18 struct tree_chain_partition 19 { 20 struct segment_tree 21 { 22 struct node 23 { 24 int sum,max; 25 int l,r,lc,rc; 26 }tr[Maxn<<1]; 27 int root; 28 void Push_Up(int x) 29 { 30 int lc=tr[x].lc; 31 int rc=tr[x].rc; 32 tr[x].sum=tr[lc].sum+tr[rc].sum; 33 tr[x].max=max(tr[lc].max,tr[rc].max); 34 } 35 void Build(int x,int l,int r) 36 { 37 tr[x].l=l; 38 tr[x].r=r; 39 if(l==r) 40 { 41 tr[x].lc=0; 42 tr[x].rc=0; 43 return; 44 } 45 tr[x].lc=x<<1; 46 tr[x].rc=(x<<1)+1; 47 int mid=(l+r)>>1; 48 Build(tr[x].lc,l,mid); 49 Build(tr[x].rc,mid+1,r); 50 } 51 void Modify(int x,int pos,int val) 52 { 53 if(tr[x].l==tr[x].r) 54 { 55 tr[x].sum=val; 56 tr[x].max=val; 57 return; 58 } 59 int mid=(tr[x].l+tr[x].r)>>1; 60 if(pos<=mid)Modify(tr[x].lc,pos,val); 61 else Modify(tr[x].rc,pos,val); 62 Push_Up(x); 63 } 64 int Query_Sum(int x,int l,int r) 65 { 66 if(tr[x].l==l&&tr[x].r==r)return tr[x].sum; 67 int mid=(tr[x].l+tr[x].r)>>1; 68 if(r<=mid)return Query_Sum(tr[x].lc,l,r); 69 else if(mid<l)return Query_Sum(tr[x].rc,l,r); 70 else return Query_Sum(tr[x].lc,l,mid)+Query_Sum(tr[x].rc,mid+1,r); 71 } 72 int Query_Max(int x,int l,int r) 73 { 74 if(tr[x].l==l&&tr[x].r==r)return tr[x].max; 75 int mid=(tr[x].l+tr[x].r)>>1; 76 if(r<=mid)return Query_Max(tr[x].lc,l,r); 77 else if(mid<l)return Query_Max(tr[x].rc,l,r); 78 else return max(Query_Max(tr[x].lc,l,mid),Query_Max(tr[x].rc,mid+1,r)); 79 } 80 }seg; 81 struct node 82 { 83 int id,fa,dep,son,top,val,size; 84 }tr[Maxn]; 85 int root; 86 struct edge 87 { 88 int y,next; 89 }road[Maxn<<1]; 90 int len; 91 int first[Maxn]; 92 void Insert(int x,int y) 93 { 94 len++; 95 road[len].y=y; 96 road[len].next=first[x]; 97 first[x]=len; 98 } 99 void Build(int x,int fa) 100 { 101 tr[x].fa=fa; 102 tr[x].son=0; 103 tr[x].size=1; 104 tr[x].dep=tr[fa].dep+1; 105 for(int k=first[x];k!=0;k=road[k].next) 106 { 107 int y=road[k].y; 108 if(y!=fa)Build(y,x); 109 } 110 tr[fa].size+=tr[x].size; 111 if(tr[tr[fa].son].size<tr[x].size)tr[fa].son=x; 112 } 113 void Modify(int x,int val) 114 { 115 tr[x].val=val; 116 seg.Modify(seg.root,tr[x].id,val); 117 } 118 int id; 119 void DFS(int x,int top) 120 { 121 tr[x].id=++id; 122 tr[x].top=top; 123 if(tr[x].son!=0)DFS(tr[x].son,top); 124 for(int k=first[x];k!=0;k=road[k].next) 125 { 126 int y=road[k].y; 127 if(y!=tr[x].fa&&y!=tr[x].son)DFS(y,y); 128 } 129 } 130 void Partitioning(int n) 131 { 132 seg.root=1; 133 seg.Build(seg.root,1,n); 134 id=0; 135 DFS(root,root); 136 } 137 int Query_Sum(int x,int y) 138 { 139 int res=0; 140 while(tr[x].top!=tr[y].top) 141 { 142 if(tr[tr[x].top].dep<tr[tr[y].top].dep)swap(x,y); 143 res+=seg.Query_Sum(seg.root,tr[tr[x].top].id,tr[x].id); 144 x=tr[tr[x].top].fa; 145 } 146 if(tr[x].dep<tr[y].dep)swap(x,y); 147 res+=seg.Query_Sum(seg.root,tr[y].id,tr[x].id); 148 return res; 149 } 150 int Query_Max(int x,int y) 151 { 152 int res=INT_MIN; 153 while(tr[x].top!=tr[y].top) 154 { 155 if(tr[tr[x].top].dep<tr[tr[y].top].dep)swap(x,y); 156 res=max(res,seg.Query_Max(seg.root,tr[tr[x].top].id,tr[x].id)); 157 x=tr[tr[x].top].fa; 158 } 159 if(tr[x].dep<tr[y].dep)swap(x,y); 160 res=max(res,seg.Query_Max(seg.root,tr[y].id,tr[x].id)); 161 return res; 162 } 163 }tra; 164 int main() 165 { 166 // freopen("a.in","r",stdin); 167 // freopen("a.out","w",stdout); 168 int n; 169 scanf("%d",&n); 170 for(int i=1;i<n;i++) 171 { 172 int x,y; 173 scanf("%d%d",&x,&y); 174 tra.Insert(x,y); 175 tra.Insert(y,x); 176 } 177 tra.root=1; 178 tra.Build(tra.root,0); 179 tra.Partitioning(n); 180 for(int i=1;i<=n;i++) 181 { 182 int x; 183 scanf("%d",&x); 184 tra.Modify(i,x); 185 } 186 int m; 187 scanf("%d",&m); 188 for(int i=1;i<=m;i++) 189 { 190 char st[6]; 191 scanf("%s",st); 192 int x,y; 193 scanf("%d%d",&x,&y); 194 if(st[1]=='S')printf("%d\n",tra.Query_Sum(x,y)); 195 else if(st[1]=='M')printf("%d\n",tra.Query_Max(x,y)); 196 else tra.Modify(x,y); 197 } 198 return 0; 199 }