首先考虑序列怎么做。。。
只要把操作差分了,记录在每个点上
然后维护一棵权值线段树,表示每个颜色出现的次数,支持单点修改和查询最大值操作
只要把序列扫一遍就好了,时间复杂度$O(n + m*logZ)$,其中$n$表述序列长度,$m$表示操作次数,$Z$表示颜色集合大小
于是树形的时候,先树链剖分,然后把操作离线,对每一条链都扫一遍就好了,时间复杂度$O(n + m*logn*logZ)$
1 /************************************************************** 2 Problem: 3307 3 User: rausen 4 Language: C++ 5 Result: Accepted 6 Time:5120 ms 7 Memory:86068 kb 8 ****************************************************************/ 9 10 #include <cstdio> 11 #include <algorithm> 12 13 using namespace std; 14 const int N = 1e5 + 5; 15 const int Z = 1e9 + 5; 16 17 inline int read(); 18 19 struct seg { 20 seg *ls, *rs; 21 int mx, wmx; 22 int tag; 23 24 seg() {} 25 26 #define Len (1 << 16) 27 inline void* operator new(size_t) { 28 static seg *mempool, *c; 29 if (mempool == c) 30 mempool = (c = new seg[Len]) + Len; 31 return c++; 32 } 33 #undef Len 34 inline void operator = (const seg &s) { 35 mx = s.mx, wmx = s.wmx; 36 } 37 38 inline void update() { 39 if (!ls && !rs) this -> mx = 0; 40 else if (!ls || !rs) *this = (ls ? *ls : *rs); 41 else if (ls -> mx >= rs -> mx) *this = *ls; 42 else *this = *rs; 43 } 44 inline void clear() { 45 tag = 1, mx = 0; 46 } 47 inline void push() { 48 if (tag) { 49 if (ls) ls -> clear(); 50 if (rs) rs -> clear(); 51 tag = 0; 52 } 53 } 54 55 #define mid (l + r >> 1) 56 void modify(int l, int r, int pos, int d) { 57 if (l == r) { 58 mx += d, wmx = l; 59 return; 60 } 61 push(); 62 if (pos <= mid) { 63 if (!ls) ls = new()seg; 64 ls -> modify(l, mid, pos, d); 65 } else { 66 if (!rs) rs = new()seg; 67 rs -> modify(mid + 1, r, pos, d); 68 } 69 update(); 70 } 71 #undef mid 72 } *T; 73 74 struct edge { 75 int next, to; 76 edge(int _n = 0, int _t = 0) : next(_n), to(_t) {} 77 } e[N << 1]; 78 int first[N], tot; 79 80 struct oper { 81 int next, z, d; 82 oper(int _n = 0, int _z = 0, int _d = 0) : next(_n), z(_z), d(_d) {} 83 } op[N << 6]; 84 int First[N], tot_op; 85 86 struct tree_node { 87 int fa, son, top; 88 int sz, dep; 89 } tr[N]; 90 91 int n, m; 92 int ans[N]; 93 94 inline void Add_Edges(int x, int y) { 95 e[++tot] = edge(first[x], y), first[x] = tot; 96 e[++tot] = edge(first[y], x), first[y] = tot; 97 } 98 99 #define y e[x].to 100 void dfs(int p) { 101 int x; 102 tr[p].sz = 1; 103 for (x = first[p]; x; x = e[x].next) 104 if (y != tr[p].fa) { 105 tr[y].fa = p, tr[y].dep = tr[p].dep + 1; 106 dfs(y); 107 tr[p].sz += tr[y].sz; 108 if (tr[tr[p].son].sz < tr[y].sz) tr[p].son = y; 109 } 110 } 111 112 void DFS(int p) { 113 int x; 114 if (!tr[p].son) return; 115 tr[tr[p].son].top = tr[p].top, DFS(tr[p].son); 116 for (x = first[p]; x; x = e[x].next) 117 if (y != tr[p].fa && y != tr[p].son) 118 tr[y].top = y, DFS(y); 119 } 120 #undef y 121 122 inline void Add_oper(int x, int y, int z) { 123 y = tr[y].son; 124 op[++tot_op] = oper(First[x], z, 1), First[x] = tot_op; 125 op[++tot_op] = oper(First[y], z, -1), First[y] = tot_op; 126 } 127 128 inline void work(int x, int y, int z) { 129 while (tr[x].top != tr[y].top) { 130 if (tr[tr[x].top].dep < tr[tr[y].top].dep) swap(x, y); 131 Add_oper(tr[x].top, x, z); 132 x = tr[tr[x].top].fa; 133 } 134 if (tr[x].dep < tr[y].dep) swap(x, y); 135 Add_oper(y, x, z); 136 } 137 138 void get_ans(int p) { 139 int x; 140 for (x = First[p]; x; x = op[x].next) 141 T -> modify(1, Z, op[x].z, op[x].d); 142 ans[p] = T -> mx == 0 ? 0 : T -> wmx; 143 if (tr[p].son) get_ans(tr[p].son); 144 } 145 146 int main() { 147 int i, x, y, z; 148 n = read(), m = read(); 149 for (i = 1; i < n; ++i) Add_Edges(read(), read()); 150 dfs(1); 151 tr[1].top = 1, DFS(1); 152 for (i = 1; i <= m; ++i) { 153 x = read(), y = read(), z = read(); 154 work(x, y, z); 155 } 156 T = new()seg; 157 for (i = 1; i <= n; ++i) 158 if (tr[i].top == i) { 159 T -> clear(); 160 get_ans(i); 161 } 162 for (i = 1; i <= n; ++i) 163 printf("%d\n", ans[i]); 164 return 0; 165 } 166 167 inline int read() { 168 static int x; 169 static char ch; 170 x = 0, ch = getchar(); 171 while (ch < '0' || '9' < ch) 172 ch = getchar(); 173 while ('0' <= ch && ch <= '9') { 174 x = x * 10 + ch - '0'; 175 ch = getchar(); 176 } 177 return x; 178 }
(p.s. 窝比较懒,所以没有把颜色离散化,直接搞了动态开点线段树)
By Xs酱~ 转载请说明
博客地址:http://www.cnblogs.com/rausen