BZOJ3999 [TJOI2015]旅游

题面:给定一个有$n$个节点的树,每个点又点权$v_i$,每次选取一条树链$[a, b]$,求出$max(v_i - v_j)$,其中$i, j in [a, b]$且$i$出现在$j$前面,最后树链$[a, b]$上的点点权都加上$v'$

裸的树链剖分,用线段树维护树链。。。查询的时候要用线段树合并。。。然后就没有然后了。。。

代码能力捉鸡QAQQQ,而且貌似是C++程序里面跑的最慢的QAQQQ

  1 /**************************************************************
  2     Problem: 3999
  3     User: rausen
  4     Language: C++
  5     Result: Accepted
  6     Time:4268 ms
  7     Memory:17988 kb
  8 ****************************************************************/
  9  
 10 #include <cstdio>
 11 #include <algorithm>
 12  
 13 using namespace std;
 14 typedef long long ll;
 15 const int N = 5e4 + 5;
 16 const int inf = 1e9;
 17  
 18 inline int read();
 19  
 20 int n;
 21 int a[N], seq[N], cnt_seq;
 22  
 23 struct edge {
 24     int next, to;
 25     edge() {}
 26     edge(int _n, int _t) : next(_n), to(_t) {}
 27 } e[N << 1];
 28  
 29 int first[N], tot;
 30  
 31 struct tree_node {
 32     int sz, dep, fa, son, v;
 33     int top, pos;
 34 } tr[N];
 35  
 36 struct seg {
 37     seg *ls, *rs, *res;
 38     ll mx, mn, mxl, mxr, tag;
 39      
 40     #define Len (1 << 16)
 41     inline void* operator new(size_t) {
 42         static seg *mempool, *c;
 43         if (mempool == c)
 44             mempool = (c = new seg[Len]) + Len;
 45         return c++;
 46     }
 47     #undef Len
 48     inline seg& operator += (int x) {
 49         mx += x, mn += x, tag += x;
 50     }
 51      
 52     inline seg* rev() {
 53         swap(mxl, mxr);
 54         return this;
 55     }
 56     inline void update(seg *ls, seg *rs) {
 57         mxl = max(max(ls -> mxl, rs -> mxl), ls -> mx - rs -> mn);      
 58         mxr = max(max(ls -> mxr, rs -> mxr), rs -> mx - ls -> mn);
 59         mx = max(ls -> mx, rs -> mx), mn = min(ls -> mn, rs -> mn);
 60     }
 61     inline void push() {
 62         if (tag) {
 63             *ls += tag, *rs += tag;
 64             tag = 0;
 65         }
 66     }
 67      
 68     #define mid (l + r >> 1)
 69     inline void build(int l, int r, int* a) {
 70         res = new()seg;
 71         if (l == r) {
 72             mx = mn = a[l];
 73             return;
 74         }
 75         ls = new()seg(), rs = new()seg;
 76         ls -> build(l, mid, a), rs -> build(mid + 1, r, a);
 77         update(ls, rs);
 78     }
 79      
 80     inline void add(int l, int r, int L, int R, int d) {
 81         if (L <= l && r <= R) {
 82             *this += d;
 83             return;
 84         }
 85         push();
 86         if (L <= mid) ls -> add(l, mid, L, R, d);
 87         if (mid < R) rs -> add(mid + 1, r, L, R, d);
 88         update(ls, rs);
 89     }
 90      
 91     inline seg* query(int l, int r, int L, int R) {
 92         if (L <= l && r <= R) {
 93             *res = *this;
 94             return res;
 95         }
 96         *res = seg(), push();
 97         if (mid >= R) res = ls -> query(l, mid, L, R);
 98         else if (mid < L) res = rs -> query(mid + 1, r, L, R);
 99         else res -> update(ls -> query(l, mid, L, R), rs -> query(mid + 1, r, L, R));
100         update(ls, rs);
101         return res;
102     }
103     #undef mid
104 } *T;
105  
106 inline void get(seg *t, int f, int a, int b, int v) {
107     if (!f) t -> update(T -> query(1, n, a, b), t);
108     else t -> update(t, T -> query(1, n, a, b) -> rev());
109     T -> add(1, n, a, b, v);
110 }
111  
112 inline void pre(seg *t) {
113     *t = seg();
114     t -> mx = t -> mxl = t -> mxr = -inf, t -> mn = inf;
115 }
116  
117 inline void work(int x, int y, int v) {
118     static seg *left = new()seg, *right = new()seg, *ans = new()seg;
119     pre(left), pre(right);
120     while (tr[x].top != tr[y].top) {
121         if (tr[tr[x].top].dep > tr[tr[y].top].dep)
122             get(right, 0, tr[tr[x].top].pos, tr[x].pos, v), x = tr[tr[x].top].fa;
123         else
124             get(left, 1, tr[tr[y].top].pos, tr[y].pos, v), y = tr[tr[y].top].fa;
125     }
126     if (tr[x].dep > tr[y].dep) get(right, 0, tr[y].pos, tr[x].pos, v);
127     else get(left, 1, tr[x].pos, tr[y].pos, v);
128     ans -> update(left, right);
129     printf("%lld
", max(ans -> mxl, 0ll));
130 }
131  
132 inline void Add_Edges(int x, int y) {
133     e[++tot] = edge(first[x], y), first[x] = tot;
134     e[++tot] = edge(first[y], x), first[y] = tot;
135 }
136  
137 #define y e[x].to
138 void dfs(int p) {
139     int x;
140     tr[p].sz = 1;
141     for (x = first[p]; x; x = e[x].next)
142         if (y != tr[p].fa) {
143             tr[y].fa = p, tr[y].dep = tr[p].dep + 1;
144             dfs(y);
145             tr[p].sz += tr[y].sz;
146             if (!tr[p].son || tr[tr[p].son].sz < tr[y].sz) tr[p].son = y;
147         }
148 }
149  
150 void DFS(int p) {
151     int x;
152     seq[tr[p].pos = ++cnt_seq] = tr[p].v;
153     if (!tr[p].son) return;
154     tr[tr[p].son].top = tr[p].top;
155     DFS(tr[p].son);
156     for (x = first[p]; x; x = e[x].next)
157         if (y != tr[p].fa && y != tr[p].son)
158             tr[y].top = y, DFS(y);
159 }
160 #undef y
161  
162 int main() {
163     int i, x, y, z, Q;
164     n = read();
165     for (i = 1; i <= n; ++i) tr[i].v = read();
166     for (i = 1; i < n; ++i)
167         Add_Edges(read(), read());
168     dfs(1);
169     tr[1].top = 1, DFS(1);
170     T = new()seg;
171     T -> build(1, n, seq);
172     for (Q = read(); Q; --Q) {
173         x = read(), y = read(), z = read();
174         work(x, y, z);
175     }
176     return 0;
177 }
178  
179 inline int read() {
180     static int x;
181     static char ch;
182     x = 0, ch = getchar();
183     while (ch < '0' || '9' < ch)
184         ch = getchar();
185     while ('0' <= ch && ch <= '9') {
186         x = x * 10 + ch - '0';
187         ch = getchar();
188     }
189     return x;
190 }
View Code
原文地址:https://www.cnblogs.com/rausen/p/4499010.html