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 }
散りぬべき 時知りてこそ 世の中の 花も花なれ 人も人なれ