【BZOJ3531】【SDOI2014】旅行
题目大意:给定一棵无根树,每个节点有自己的类别和权值,现在给定两个类别相同的点,叫你求这2点路径上同类别节点的权值和/最大权值。
节点类别与权值会改变。
解题思路:考虑对每一个类别开一棵线段树,动态开点,可以写指针,也可以开数组写链表,然后剩下的就是树剖的东西了。我写的是指针,跑的略慢一些,时间效率为\( O(q \log^{2} n) \).
代码由于是在自家的mac上码的,所以和以前风格不大一样。
1 #include <stdio.h> 2 #define MN 100005 3 inline void swp(int &a,int &b){a ^= b ^= a ^= b;} 4 inline int max(int a,int b){return a > b ? a : b;} 5 inline int in(){ 6 int x = 0 ,f = 1; char ch = getchar(); 7 while (ch < '0' || ch > '9') f = ch=='-' ? -1 :1 , ch = getchar(); 8 while (ch >= '0' && ch <= '9' ) x = (x<<3) + (x<<1) + ch - '0',ch = getchar(); 9 return x*f; 10 } 11 struct segment_tree{ 12 segment_tree *ls , *rs; 13 int sum,ma; 14 void combine(){ 15 sum = ma = 0; 16 if (ls != NULL){ 17 sum += ls -> sum; 18 ma = max( ma , ls -> ma ); 19 }if (rs != NULL){ 20 sum += rs -> sum; 21 ma = max( ma , rs -> ma ); 22 } 23 } 24 segment_tree (int sum=0,int ma=0):sum(sum),ma(ma){ls = rs = NULL;} 25 }*ST[MN]; 26 #define S_T segment_tree 27 int to[MN<<1],nxt[MN<<1],cnt,head[MN]; 28 int n,q,top[MN],siz[MN],son[MN],val[MN],belief[MN],fa[MN],dep[MN],pos[MN],dfsn; 29 inline void ins(int x,int y){to[++cnt] = y , nxt[cnt] = head[x] , head[x] = cnt;} 30 inline void insw(int x,int y){ins(x,y); ins(y,x);} 31 inline void dfs1(int u,int f,int d){ 32 siz[u] = 1; dep[u] = d; fa[u] = f; 33 for (register int i = head[u]; i; i = nxt[i]) 34 if (to[i] != f) { 35 dfs1(to[i],u,d+1); siz[u] += siz[to[i]]; 36 if (siz[son[u]] < siz[to[i]]) son[u] = to[i]; 37 } 38 } 39 inline void dfs2(int u,int tp){ 40 top[u] = tp; pos[u] = (++dfsn); if (son[u]) dfs2(son[u],tp); 41 for (register int i = head[u]; i; i = nxt[i]) 42 if (to[i] != fa[u] && to[i] != son[u]) dfs2(to[i],to[i]); 43 } 44 #define mid (l+r>>1) 45 inline void insert(S_T* &x,int l,int r,int pos,int val){ 46 if (x == NULL) x = new S_T; 47 if (l == r){x -> sum = x -> ma = val; return;} 48 if (pos <= mid) insert(x -> ls,l,mid,pos,val); 49 else insert(x -> rs,mid+1,r,pos,val);x->combine(); 50 } 51 inline void Delete(S_T* &x,int l,int r,int pos){ 52 if (l==r){delete x; x = NULL; return; } 53 if (pos<=mid) Delete(x -> ls,l,mid,pos); 54 else Delete(x -> rs,mid+1,r,pos); 55 if (x -> ls == NULL && x -> rs == NULL){delete x; x = NULL; return; } 56 else x -> combine(); 57 } 58 inline int QM(S_T* &x,int l,int r,int a,int b){ 59 if (x == NULL) return 0; 60 if (l == a && r == b) return x -> ma; 61 if (b<=mid) return QM(x -> ls,l,mid,a,b); 62 if (a>mid) return QM(x -> rs,mid+1,r,a,b); 63 return max(QM(x -> ls,l,mid,a,mid),QM(x -> rs,mid+1,r,mid+1,b)); 64 } 65 inline int QS(S_T* &x,int l,int r,int a,int b){ 66 if (x == NULL) return 0; 67 if (l == a && r == b) return x -> sum; 68 if (b<=mid) return QS(x -> ls,l,mid,a,b); 69 if (a>mid) return QS(x -> rs,mid+1,r,a,b); 70 return QS(x -> ls,l,mid,a,mid)+QS(x -> rs,mid+1,r,mid+1,b); 71 } 72 inline int qm(int belief,int x,int y){ 73 register int res = 0; 74 while (top[x] != top[y]){ 75 if (dep[top[x]] < dep[top[y]]) swp(x,y); 76 res = max(res,QM(ST[belief],1,n,pos[top[x]],pos[x])); 77 x = fa[top[x]]; 78 }if (dep[x] > dep[y]) swp(x,y);res = max(res,QM(ST[belief],1,n,pos[x],pos[y])); 79 return res; 80 } 81 inline int qs(int belief,int x,int y){ 82 register int res = 0; 83 while (top[x] != top[y]){ 84 if (dep[top[x]] < dep[top[y]]) swp(x,y); 85 res += QS(ST[belief],1,n,pos[top[x]],pos[x]); 86 x = fa[top[x]]; 87 }if (dep[x] > dep[y]) swp(x,y);res += QS(ST[belief],1,n,pos[x],pos[y]); 88 return res; 89 } 90 void init(){ 91 n = in() , q = in(); 92 for (int i = 1; i <= n; ++i) val[i] = in() , belief[i] = in(); 93 for (register int i = 1; i < n; ++i) insw(in(),in()); 94 dfs1(1,1,1);dfs2(1,1); 95 for (register int i = 1; i <= n; ++i) 96 insert(ST[belief[i]],1,n,pos[i],val[i]); 97 } 98 void solve(){ 99 while(q--){ 100 register char op[5]; scanf("%s",op); 101 register int x=in(),y=in(); 102 if (op[0] == 'C'){ 103 if (op[1] == 'C'){ 104 Delete(ST[belief[x]],1,n,pos[x]); 105 insert(ST[belief[x] = y],1,n,pos[x],val[x]); 106 }else insert(ST[belief[x]],1,n,pos[x],val[x]=y); 107 }else{ 108 if (op[1] == 'M') printf("%d\n",qm(belief[x],x,y)); 109 else printf("%d\n",qs(belief[x],x,y)); 110 } 111 } 112 } 113 int main(){ init(); solve();}