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

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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

Sample Output

4
1
2
2
10
6
5
6
5
16

HINT

Source

Solution

  剖一下,线段树维护一下。

  模板题……

Code

技术分享
  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 }
View Code

 

以上是关于BZOJ1036: [ZJOI2008]树的统计Count - 树链剖分 -的主要内容,如果未能解决你的问题,请参考以下文章

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

BZOJ 1036: [ZJOI2008]树的统计Count

bzoj 1036: [ZJOI2008]树的统计Count

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

bzoj 1036 [ZJOI2008]树的统计Count(树链剖分,线段树)

[Bzoj1036][ZJOI2008]树的统计Count