标签:
题目链接:http://www.lydsy.com/JudgeOnline/problem.php?id=1036
解:树链剖分裸题,树链剖分基础=线段树+Tarjan求LCA
树剖其实就是把树拆成链再组合起来变成线性表,然后用线段树对线性表处理就好了
树剖学习推荐博客:http://blog.sina.com.cn/s/blog_6974c8b20100zc61.html
1 /* 2 * Problem: 3 * Author: SHJWUDP 4 * Created Time: 2015/6/10 星期三 23:13:56 5 * File Name: 233.cpp 6 * State: 7 * Memo: 8 */ 9 #include <iostream> 10 #include <cstdio> 11 #include <cstring> 12 #include <algorithm> 13 14 using namespace std; 15 16 const int MaxA=3e4+7; 17 18 struct Edge { 19 int v, nt; 20 Edge(){} 21 Edge(int v, int nt):v(v), nt(nt){} 22 } edges[MaxA<<1]; 23 24 int head[MaxA], edgeNum; 25 26 struct SegmentTree { 27 int n; 28 struct Node { 29 int mx; 30 int sum; 31 } c[MaxA<<2]; 32 int *val; 33 int p, v; 34 int L, R; 35 #define lson l, m, rt<<1 36 #define rson m+1, r, rt<<1|1 37 38 void pushUp(int rt) { 39 c[rt].mx=max(c[rt<<1].mx, c[rt<<1|1].mx); 40 c[rt].sum=c[rt<<1].sum+c[rt<<1|1].sum; 41 } 42 43 void doBuild(int l, int r, int rt) { 44 if(l==r) { 45 c[rt].mx=c[rt].sum=val[l]; 46 } else { 47 int m=(l+r)>>1; 48 doBuild(lson); 49 doBuild(rson); 50 pushUp(rt); 51 } 52 } 53 54 void build(int n, int* val) { 55 this->n=n; this->val=val; 56 doBuild(1, n, 1); 57 } 58 59 void doUpdate(int l, int r, int rt) { 60 if(l==r) { 61 c[rt].mx=c[rt].sum=v; 62 } else { 63 int m=(l+r)>>1; 64 if(p<=m) doUpdate(lson); 65 else doUpdate(rson); 66 pushUp(rt); 67 } 68 } 69 70 void update(int p, int v) { 71 this->p=p; this->v=v; 72 doUpdate(1, n, 1); 73 } 74 75 int doqmax(int l, int r, int rt) { 76 if(L<=l && r<=R) { 77 return c[rt].mx; 78 } else { 79 int m=(l+r)>>1; 80 int res=0x80000000; 81 if(L<=m) res=max(res, doqmax(lson)); 82 if(m<R) res=max(res, doqmax(rson)); 83 return res; 84 } 85 } 86 87 int qmax(int L, int R) { 88 this->L=L; this->R=R; 89 return doqmax(1, n, 1); 90 } 91 92 int doqsum(int l, int r, int rt) { 93 if(L<=l && r<=R) { 94 return c[rt].sum; 95 } else { 96 int m=(l+r)>>1; 97 int res=0; 98 if(L<=m) res+=doqsum(lson); 99 if(m<R) res+=doqsum(rson); 100 return res; 101 } 102 } 103 104 int qsum(int L, int R) { 105 this->L=L; this->R=R; 106 return doqsum(1, n, 1); 107 } 108 #undef lson 109 #undef rson 110 } st; 111 112 int N; 113 int oval[MaxA], val[MaxA]; 114 void init() { 115 edgeNum=0; 116 memset(head, -1, sizeof(head)); 117 } 118 void addEdge(int u, int v) { 119 edges[edgeNum]=Edge(v, head[u]); 120 head[u]=edgeNum++; 121 } 122 namespace LCT { 123 int fa[MaxA]; 124 int son[MaxA]; 125 int dep[MaxA]; 126 int siz[MaxA]; 127 int w[MaxA]; 128 int top[MaxA]; 129 int id; 130 131 int dfs1(int u, int d) { 132 siz[u]=1; dep[u]=d; son[u]=-1; 133 for(int i=head[u]; ~i; i=edges[i].nt) { 134 Edge& e=edges[i]; 135 if(e.v==fa[u]) continue; 136 fa[e.v]=u; 137 siz[u]+=dfs1(e.v, d+1); 138 if(son[u]==-1 || siz[son[u]]<siz[e.v]) son[u]=e.v; 139 } 140 return siz[u]; 141 } 142 143 void dfs2(int u, int tp) { 144 w[u]=++id; top[u]=tp; 145 if(son[u]!=-1) dfs2(son[u], tp); 146 for(int i=head[u]; ~i; i=edges[i].nt) { 147 Edge& e=edges[i]; 148 if(e.v==fa[u] || e.v==son[u]) continue; 149 dfs2(e.v, e.v); 150 } 151 } 152 153 int query(int u, int v, int op) { 154 int res; 155 if(op==0) res=0; 156 else res=0x80000000; 157 int f1=top[u], f2=top[v]; 158 while(f1!=f2) { 159 if(dep[f1]<dep[f2]) { swap(f1, f2); swap(u, v); } 160 if(op==0) res+=st.qsum(w[f1], w[u]); 161 else res=max(res, st.qmax(w[f1], w[u])); 162 u=fa[f1]; f1=top[u]; 163 } 164 if(dep[u]>dep[v]) swap(u, v); 165 if(op==0) res+=st.qsum(w[u], w[v]); 166 else res=max(res, st.qmax(w[u], w[v])); 167 return res; 168 } 169 170 void update(int p, int v) { 171 st.update(w[p], v); 172 } 173 174 void init() { 175 int root=1; 176 id=0; 177 fa[root]=-1; 178 dfs1(root, 0); 179 dfs2(root, root); 180 for(int i=1; i<=N; i++) { 181 val[w[i]]=oval[i]; 182 } 183 st.build(N, val); 184 } 185 } 186 int main() { 187 #ifndef ONLINE_JUDGE 188 freopen("in", "r", stdin); 189 //freopen("out", "w", stdout); 190 #endif 191 while(~scanf("%d", &N)) { 192 init(); 193 for(int i=1; i<N; i++) { 194 int a, b; 195 scanf("%d%d", &a, &b); 196 addEdge(a, b); 197 addEdge(b, a); 198 } 199 for(int i=1; i<=N; i++) { 200 scanf("%d", &oval[i]); 201 } 202 LCT::init(); 203 int Q; 204 scanf("%d", &Q); 205 while(Q--) { 206 char op[7]; 207 int a, b; 208 scanf("%s%d%d", op, &a, &b); 209 if(op[0]==‘C‘) { 210 LCT::update(a, b); 211 } else { 212 if(op[1]==‘S‘) { 213 printf("%d\n", LCT::query(a, b, 0)); 214 } else printf("%d\n", LCT::query(a, b, 1)); 215 } 216 } 217 } 218 return 0; 219 }
bzoj 1036: [ZJOI2008]树的统计Count
标签:
原文地址:http://www.cnblogs.com/shjwudp/p/4567885.html