bzoj1036 [ZJOI2008]树的统计Count (树链剖分+线段树)

1036: [ZJOI2008]树的统计Count

Time Limit: 10 Sec  Memory Limit: 162 MB
Submit: 17941  Solved: 7305
[Submit][Status][Discuss]

Description

  一棵树上有n个节点,编号分别为1到n,每个节点都有一个权值w。我们将以下面的形式来要求你对这棵树完成一些操作:

  I. CHANGE u t : 把结点u的权值改为t

  II. QMAX u v: 询问从点u到点v的路径上的节点的最大权值

  III. 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”的操作,每行输出一个整数表示要求输出的结果。

 

 

树剖模板dearu;

 

↓代码

  1 #include<iostream>
  2 #include<cstdio>
  3 #include<cstring>
  4 #include<string>
  5 #include<cmath>
  6 #include<algorithm>
  7 #include<vector>
  8 #include<complex>
  9 #define N 50039
 10 #define inf 0x7fffffff 
 11 #define ll long long
 12 using namespace std;
 13 struct segtree
 14 {
 15     int l,r,m,w,lazy;
 16     bool clr()
 17     {
 18         lazy=w=0;
 19         m=-inf;
 20     }
 21 }tree[4*N];
 22 vector<int> map[N];
 23 int dep[N],siz[N],fa[N],son[N],top[N],id[N],tot=0;
 24 void get_size(int pos,int pre,int de)
 25 {
 26     dep[pos]=de,son[pos]=0,siz[pos]=1,fa[pos]=pre;
 27     int a,b;
 28     for(a=0;a<map[pos].size();a++)
 29     {
 30         b=map[pos][a];
 31         if(b!=pre)
 32         {
 33             get_size(b,pos,de+1);
 34             siz[pos]+=siz[b];
 35             if(siz[b]>siz[son[pos]])
 36             {
 37                 son[pos]=b;
 38             }
 39         }
 40     }
 41 }
 42 void get_id(int pos,int tp)
 43 {
 44     top[pos]=tp,id[pos]=++tot;
 45     if(son[pos]!=0)
 46     {
 47         get_id(son[pos],tp);
 48     }
 49     int a,b;
 50     for(a=0;a<map[pos].size();a++)
 51     {
 52         b=map[pos][a];
 53         if(b!=son[pos] && b!=fa[pos])
 54         {
 55             get_id(b,b);
 56         }
 57     }
 58 }
 59 void pull_up(int k)
 60 {
 61     tree[k].w=tree[2*k].w+tree[2*k+1].w;
 62     tree[k].m=max(tree[2*k].m,tree[2*k+1].m);
 63 }
 64 void build_tree(int k,int l,int r)
 65 {
 66     tree[k].l=l,tree[k].r=r;
 67     tree[k].clr();
 68     if(l==r)
 69     {
 70         return;
 71     }
 72     int mid=(l+r)>>1;
 73     build_tree(2*k,l,mid);
 74     build_tree(2*k+1,mid+1,r);
 75 }
 76 void update_single(int k,int pos,int val)
 77 {
 78     if(tree[k].l==pos && tree[k].r==pos)
 79     {
 80         tree[k].w=tree[k].m=val;
 81         return;
 82     }
 83     if(tree[k].r<pos || tree[k].l>pos)
 84     {
 85         return;
 86     }
 87     update_single(2*k,pos,val);
 88     update_single(2*k+1,pos,val);
 89     pull_up(k); 
 90 }
 91 int query_sum(int k,int l,int r)
 92 {
 93     if(tree[k].l>=l && tree[k].r<=r)
 94     {
 95         return tree[k].w;
 96     }
 97     if(tree[k].r<l || tree[k].l>r)
 98     {
 99         return 0;
100     }
101     return query_sum(2*k,l,r)+query_sum(2*k+1,l,r);
102 }
103 int query_max(int k,int l,int r)
104 {
105     if(tree[k].l>=l && tree[k].r<=r)
106     {
107         return tree[k].m;
108     }
109     if(tree[k].r<l || tree[k].l>r)
110     {
111         return -inf;
112     }
113     return max(query_max(2*k,l,r),query_max(2*k+1,l,r));
114 } 
115 int solve_sum(int i,int j)
116 {
117     int res=0;
118     while(top[i]!=top[j])
119     {
120         if(dep[top[i]]<dep[top[j]])
121         {
122             swap(i,j);
123         }
124         res+=query_sum(1,id[top[i]],id[i]);
125         i=fa[top[i]];
126     }
127     if(id[i]>id[j])
128     {
129         swap(i,j);
130     }
131     res+=query_sum(1,id[i],id[j]);
132     return res;
133 }
134 int solve_max(int i,int j)
135 {
136     int res=-inf;
137     while(top[i]!=top[j])
138     {
139         if(dep[top[i]]<dep[top[j]])
140         {
141             swap(i,j);
142         }
143         res=max(res,query_max(1,id[top[i]],id[i]));
144         i=fa[top[i]];
145     }
146     if(id[i]>id[j])
147     {
148         swap(i,j);
149     }
150     res=max(res,query_max(1,id[i],id[j]));
151     return res;
152 }
153 int main()
154 {
155     char ch[39];
156     int n,m,a,b,c;
157     scanf("%d",&n);
158     for(a=1;a<n;a++)
159     {
160         scanf("%d%d",&b,&c);
161         map[b].push_back(c);
162         map[c].push_back(b);
163     }
164     siz[0]=-1;
165     get_size(1,1,0);
166     get_id(1,1);
167     build_tree(1,1,n);
168     for(a=1;a<=n;a++)
169     {
170         scanf("%d",&b);
171         update_single(1,id[a],b);
172     }
173     scanf("%d",&m);
174     while(m--)
175     {
176         scanf("%s",ch);
177         scanf("%d%d",&a,&b);
178         if(ch[0]=='C')
179         {
180             update_single(1,id[a],b); 
181         }
182         else
183         {
184             if(ch[1]=='S')
185             {
186                 printf("%d\n",solve_sum(a,b));
187             }
188             if(ch[1]=='M')
189             {
190                 printf("%d\n",solve_max(a,b)); 
191             }
192         }
193     }
194     return 0;
195 }
bzoj1036

 

posted @ 2017-08-14 23:11  Sinogi  阅读(214)  评论(0编辑  收藏  举报