bzoj3531: [Sdoi2014]旅行 (树链剖分 && 动态开点线段树)
感觉动态开点线段树空间复杂度好优秀呀
树剖裸题
把每个宗教都开一颗线段树就可以了
但是我一直TLE
然后调了一个小时
为什么呢
因为我 #define max(x, y) (x > y ? x : y)
看起来好像可以减少常数的样子
我也是这么想的(作死
事实上
ans = max(ans, query(x, y))
类似这种语句中
query(x, y)会计算两次
然后就GG了
这告诉我们还是好好用库里的函数吧
1 #include <cstdio> 2 #include <algorithm> 3 #include <vector> 4 using namespace std; 5 const int N = 100000 + 10; 6 const int M = 2000000 + 10; 7 #define isdigit(x) (x >= '0' && x <= '9') 8 9 inline void read(int &ans) { 10 ans = 0; 11 static char buf = getchar(); 12 register int res = 1; 13 for (; !isdigit(buf); buf = getchar()) 14 if (buf == '-') res = -1; 15 for (; isdigit(buf); buf = getchar()) 16 ans = ans * 10 + buf - '0'; 17 ans *= res; 18 } 19 20 int tot, n, q; 21 int sz[N], hs[N], pos[N], fa[N], top[N], w[N], c[N], dep[N]; 22 vector < int > E[N]; 23 24 void dfs1(int x, int d, int f) { 25 dep[x] = d; fa[x] = f; 26 hs[x] = -1; sz[x] = 1; 27 int tmp = 0; 28 for (int i = 0; i < E[x].size(); i++) { 29 int u = E[x][i]; 30 if (u == f) continue; 31 dfs1(u, d + 1, x); 32 sz[x] += sz[u]; 33 if (tmp < sz[u]) 34 tmp = sz[u], hs[x] = u; 35 } 36 } 37 38 void dfs2(int x, int t) { 39 top[x] = t; pos[x] = ++tot; 40 if (hs[x] == -1) return; 41 dfs2(hs[x], t); 42 for (int i = 0; i < E[x].size(); i++) 43 if (E[x][i] != fa[x] && E[x][i] != hs[x]) 44 dfs2(E[x][i], E[x][i]); 45 } 46 47 int cnt; 48 int sum[M], maxn[M], ls[M], rs[M], root[N]; 49 50 inline void pushUp(int o) { 51 maxn[o] = max(maxn[ls[o]], maxn[rs[o]]); 52 sum[o] = sum[ls[o]] + sum[rs[o]]; 53 } 54 55 void modify(int &o, int l, int r, int p, int c) { 56 if (!o) o = ++cnt; 57 if (l == r) { 58 sum[o] = maxn[o] = c; 59 return ; 60 } 61 int mid = l + r >> 1; 62 if (p <= mid) modify(ls[o], l, mid, p, c); 63 else modify(rs[o], mid + 1, r, p, c); 64 pushUp(o); 65 } 66 67 int querySum(int o, int l, int r, int L, int R) { 68 if (!o) return 0; 69 if (l >= L && r <= R) return sum[o]; 70 int mid = l + r >> 1, ans = 0; 71 if (L <= mid) ans += querySum(ls[o], l, mid, L, R); 72 if (R > mid) ans += querySum(rs[o], mid + 1, r, L, R); 73 return ans; 74 } 75 76 inline int querySum(int c, int x, int y) { 77 int f1 = top[x], f2 = top[y]; 78 int ans = 0; 79 while (f1 != f2) { 80 if (dep[f1] < dep[f2]) 81 swap(x, y), swap(f1, f2); 82 ans += querySum(root[c], 1, n, pos[f1], pos[x]); 83 x = fa[f1]; f1 = top[x]; 84 } 85 if (dep[x] > dep[y]) swap(x, y); 86 ans += querySum(root[c], 1, n, pos[x], pos[y]); 87 return ans; 88 } 89 90 int queryMax(int o, int l, int r, int L, int R) { 91 if (!o) return 0; 92 if (l >= L && r <= R) return maxn[o]; 93 int mid = l + r >> 1, ans = 0; 94 if (L <= mid) ans = max(ans, queryMax(ls[o], l, mid, L, R)); 95 if (R > mid) ans = max(ans, queryMax(rs[o], mid + 1, r, L, R)); 96 return ans; 97 } 98 99 inline int queryMax(int c, int x, int y) { 100 int f1 = top[x], f2 = top[y]; 101 int ans = 0; 102 while (f1 != f2) { 103 if (dep[f1] < dep[f2]) 104 swap(x, y), swap(f1, f2); 105 ans = max(ans, queryMax(root[c], 1, n, pos[f1], pos[x])); 106 x = fa[f1]; f1 = top[x]; 107 } 108 if (dep[x] > dep[y]) swap(x, y); 109 ans = max(ans, queryMax(root[c], 1, n, pos[x], pos[y])); 110 return ans; 111 } 112 113 114 int main() { 115 read(n); read(q); 116 for (int i = 1; i <= n; i++) 117 read(w[i]), read(c[i]); 118 for (int i = 1; i < n; i++) { 119 int u, v; 120 read(u); read(v); 121 E[u].push_back(v); 122 E[v].push_back(u); 123 } 124 dfs1(1, 0, 0); dfs2(1, 1); 125 for (int i = 1; i <= n; i++) 126 modify(root[c[i]], 1, n, pos[i], w[i]); 127 for (int i = 1; i <= q; i++) { 128 char ch[5]; scanf("%s", ch); 129 int x, y; read(x); read(y); 130 if (ch[0] == 'C') { 131 if (ch[1] == 'C') { 132 modify(root[c[x]], 1, n, pos[x], 0); 133 c[x] = y; 134 modify(root[y], 1, n, pos[x], w[x]); 135 } 136 else { 137 modify(root[c[x]], 1, n, pos[x], y); 138 w[x] = y; 139 } 140 } 141 else { 142 if (ch[1] == 'S') 143 printf("%d\n", querySum(c[x], x, y)); 144 else printf("%d\n", queryMax(c[x], x, y)); 145 } 146 } 147 return 0; 148 }