首先考虑序列怎么做。。。

只要把操作差分了,记录在每个点上

然后维护一棵权值线段树,表示每个颜色出现的次数,支持单点修改和查询最大值操作

只要把序列扫一遍就好了,时间复杂度$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 }
View Code

(p.s. 窝比较懒,所以没有把颜色离散化,直接搞了动态开点线段树)

posted on 2015-05-16 11:57  Xs酱~  阅读(256)  评论(0编辑  收藏  举报