[SDOI2014]旅行
总算把几个月前WA的题A了。
看到树上路径的操作,就能想到树剖。
不过要是给每一个宗教都开一个线段树的话肯定会MLE,所以我们动态开点就行啦。
然后debug了一小会儿,全是因为一些zz小错误,什么连接表遍历出边写错了,查询最大值从查询区间和复制下来却没改完……对了,这两个最好分开写,虽然代码可能会长一点,但是每一个函数里面结构还是特别清晰的。
![](https://images.cnblogs.com/OutliningIndicators/ContractedBlock.gif)
1 #include<cstdio> 2 #include<iostream> 3 #include<cmath> 4 #include<algorithm> 5 #include<cstring> 6 #include<cstdlib> 7 #include<cctype> 8 #include<vector> 9 #include<stack> 10 #include<queue> 11 using namespace std; 12 #define enter puts("") 13 #define space putchar(' ') 14 #define Mem(a, x) memset(a, x, sizeof(a)) 15 #define rg register 16 typedef long long ll; 17 typedef double db; 18 const int INF = 0x3f3f3f3f; 19 const db eps = 1e-8; 20 const int maxn = 1e5 + 5; 21 const int max_tre = 1e7 + 5; 22 inline ll read() 23 { 24 ll ans = 0; 25 char ch = getchar(), last = ' '; 26 while(!isdigit(ch)) {last = ch; ch = getchar();} 27 while(isdigit(ch)) {ans = ans * 10 + ch - '0'; ch = getchar();} 28 if(last == '-') ans = -ans; 29 return ans; 30 } 31 inline void write(ll x) 32 { 33 if(x < 0) x = -x, putchar('-'); 34 if(x >= 10) write(x / 10); 35 putchar(x % 10 + '0'); 36 } 37 38 int n, q, w[maxn], c[maxn]; 39 40 struct Edge 41 { 42 int nxt, to; 43 }e[maxn << 1]; 44 int head[maxn], ecnt = 0; 45 void addEdge(int x, int y) 46 { 47 e[++ecnt] = (Edge){head[x], y}; 48 head[x] = ecnt; 49 } 50 51 int dep[maxn], fa[maxn], siz[maxn], son[maxn]; 52 void dfs1(int now, int f) 53 { 54 siz[now] = 1; 55 for(int i = head[now]; i; i = e[i].nxt) 56 { 57 if(e[i].to == f) continue; 58 dep[e[i].to] = dep[now] + 1; 59 fa[e[i].to] = now; 60 dfs1(e[i].to, now); 61 siz[now] += siz[e[i].to]; 62 if(!son[now] || siz[son[now]] < siz[e[i].to]) son[now] = e[i].to; 63 } 64 } 65 int top[maxn], dfsx[maxn], cnt = 0; 66 void dfs2(int now, int f) 67 { 68 dfsx[now] = ++cnt; 69 if(son[now]) 70 { 71 top[son[now]] = top[now]; 72 dfs2(son[now], now); 73 } 74 for(int i = head[now]; i; i = e[i].nxt) 75 { 76 if(e[i].to == son[now] || e[i].to == f) continue; 77 top[e[i].to] = e[i].to; 78 dfs2(e[i].to, now); 79 } 80 } 81 82 int ctr = 0, root[maxn], ls[max_tre], rs[max_tre], Max[max_tre], sum[max_tre]; 83 void update(int &now, int l, int r, int idx, int d) 84 { 85 if(!now) now = ++ctr; 86 if(l == r) {Max[now] = sum[now] = d; return;} 87 int mid = (l + r) >> 1; 88 if(idx <= mid) update(ls[now], l, mid, idx, d); 89 else update(rs[now], mid + 1, r, idx, d); 90 sum[now] = sum[ls[now]] + sum[rs[now]]; 91 Max[now] = max(Max[ls[now]], Max[rs[now]]); 92 } 93 int query_Sum(int now, int l, int r, int L, int R) 94 { 95 if(!now) return 0; 96 if(l == L && r == R) return sum[now]; 97 int mid = (l + r) >> 1; 98 if(R <= mid) return query_Sum(ls[now], l, mid, L, R); 99 else if(L > mid) return query_Sum(rs[now], mid + 1, r, L, R); 100 else return query_Sum(ls[now], l, mid, L, mid) + query_Sum(rs[now], mid + 1, r, mid + 1, R); 101 } 102 int query_Max(int now, int l, int r, int L, int R) 103 { 104 if(!now) return 0; 105 if(l == L && r == R) return Max[now]; 106 int mid = (l + r) >> 1; 107 if(R <= mid) return query_Max(ls[now], l, mid, L, R); 108 else if(L > mid) return query_Max(rs[now], mid + 1, r, L, R); 109 else return max(query_Max(ls[now], l, mid, L, mid), query_Max(rs[now], mid + 1, r, mid + 1, R)); 110 } 111 int queryS_path(int x, int y) 112 { 113 int col = c[x], ret = 0; 114 while(top[x] != top[y]) 115 { 116 if(dep[top[x]] < dep[top[y]]) swap(x, y); 117 ret += query_Sum(root[col], 1, cnt, dfsx[top[x]], dfsx[x]); 118 x = fa[top[x]]; 119 } 120 if(dfsx[x] < dfsx[y]) swap(x, y); 121 ret += query_Sum(root[col], 1, cnt, dfsx[y], dfsx[x]); 122 return ret; 123 } 124 int queryM_path(int x, int y) 125 { 126 int col = c[x], ret = 0; 127 while(top[x] != top[y]) 128 { 129 if(dep[top[x]] < dep[top[y]]) swap(x, y); 130 ret = max(ret, query_Max(root[col], 1, cnt, dfsx[top[x]], dfsx[x])); 131 x = fa[top[x]]; 132 } 133 if(dfsx[x] < dfsx[y]) swap(x, y); 134 ret = max(ret, query_Max(root[col], 1, cnt, dfsx[y], dfsx[x])); 135 return ret; 136 } 137 138 char s[2]; 139 140 int main() 141 { 142 n = read(); q = read(); 143 for(int i = 1; i <= n; ++i) w[i] = read(), c[i] = read(); 144 for(int i = 1; i < n; ++i) 145 { 146 int x = read(), y = read(); 147 addEdge(x, y); addEdge(y, x); 148 } 149 dfs1(1, 0); top[1] = 1; dfs2(1, 0); 150 for(int i = 1; i <= n; ++i) update(root[c[i]], 1, cnt, dfsx[i], w[i]); 151 for(int i = 1; i <= q; ++i) 152 { 153 scanf("%s", s); int x = read(), y = read(); 154 if(s[1] == 'C') 155 { 156 update(root[c[x]], 1, cnt, dfsx[x], 0); 157 c[x] = y; 158 update(root[c[x]], 1, cnt, dfsx[x], w[x]); 159 } 160 else if(s[1] == 'W') 161 { 162 w[x] = y; 163 update(root[c[x]], 1, cnt, dfsx[x], w[x]); 164 } 165 else if(s[1] == 'S') write(queryS_path(x, y)), enter; 166 else write(queryM_path(x, y)), enter; 167 } 168 return 0; 169 }