LOJ#2722 情报中心

解:有个暴力是枚举两条链然后O(n)判定,可以得到15分。

还可以优化一下,枚举一条链,然后第二条链直接求两端点树上带权距离。可以做到O(m(n + m)),但是我用的树剖,跟上面那一档没啥区别Orz...

然后是链的部分,把所有链按照左端点小到大排序,左端点相同的时候按右端点小到大。

然后从右往左加。用一个树状数组维护前缀最大值。如果一个之前区间的左端点在我们当前区间的右端点内,就有交。

我们漏了一种情况:一个区间被另一个完全包含。于是新开一个树状数组维护即可。注意到这种情况在第一个树状数组中算出的答案不优,会被取代掉。

这样就有30分了。

  1 /**
  2  * There is no end though there is a start in space. ---Infinity.
  3  * It has own power, it ruins, and it goes though there is a start also in the star. ---Finite.
  4  * Only the person who was wisdom can read the most foolish one from the history.
  5  * The fish that lives in the sea doesn't know the world in the land.
  6  * It also ruins and goes if they have wisdom.
  7  * It is funnier that man exceeds the speed of light than fish start living in the land.
  8  * It can be said that this is an final ultimatum from the god to the people who can fight.
  9  *
 10  * Steins;Gate
 11  */
 12 
 13 #include <bits/stdc++.h>
 14 
 15 #define forson(x, i) for(int i = e[x]; i; i = edge[i].nex)
 16 
 17 typedef long long LL;
 18 const int N = 100010;
 19 const LL INF = 9e18;
 20 
 21 struct Edge {
 22     int nex, v;
 23     LL len;
 24 }edge[N << 1]; int tp;
 25 
 26 struct Node {
 27     int x, y;
 28     LL z, val;
 29     inline bool operator < (const Node &w) const {
 30         if(x != w.x) return x < w.x;
 31         return y < w.y;
 32     }
 33 }node[N];
 34 
 35 int n, e[N], m, fa[N], deep[N];
 36 int num, pos[N], son[N], siz[N], top[N];
 37 LL Sum[N], sum[N << 2], d[N], tag[N << 2];
 38 
 39 inline void add(int x, int y, LL z) {
 40     tp++;
 41     edge[tp].v = y;
 42     edge[tp].len = z;
 43     edge[tp].nex = e[x];
 44     e[x] = tp;
 45     return;
 46 }
 47 
 48 void DFS_1(int x, int f) { /// get fa son siz d deep
 49     fa[x] = f;
 50     deep[x] = deep[f] + 1;
 51     siz[x] = 1;
 52     forson(x, i) {
 53         int y = edge[i].v;
 54         if(y == f) continue;
 55         d[y] = d[x] + edge[i].len;
 56         DFS_1(y, x);
 57         siz[x] += siz[y];
 58         if(siz[y] > siz[son[x]]) {
 59             son[x] = y;
 60         }
 61     }
 62     return;
 63 }
 64 
 65 void DFS_2(int x, int f) { /// get top id pos
 66     pos[x] = ++num;
 67     top[x] = f;
 68     Sum[num] = d[x] - d[fa[x]];
 69     if(son[x]) {
 70         DFS_2(son[x], f);
 71     }
 72     forson(x, i) {
 73         int y = edge[i].v;
 74         if(y == fa[x] || y == son[x]) continue;
 75         DFS_2(y, y);
 76     }
 77     return;
 78 }
 79 
 80 inline int lca(int x, int y) {
 81     while(top[x] != top[y]) {
 82         if(deep[top[x]] > deep[top[y]]) {
 83             x = fa[top[x]];
 84         }
 85         else {
 86             y = fa[top[y]];
 87         }
 88     }
 89     return deep[x] < deep[y] ? x : y;
 90 }
 91 
 92 inline LL dis(int x, int y) {
 93     return d[x] + d[y] - 2 * d[lca(x, y)];
 94 }
 95 
 96 inline void pushdown(int l, int r, int o) {
 97     if(tag[o] != -1) {
 98         if(tag[o] == 0) {
 99             sum[o << 1] = sum[o << 1 | 1] = 0;
100         }
101         else {
102             int mid = (l + r) >> 1;
103             sum[o << 1] = Sum[mid] - Sum[l - 1];
104             sum[o << 1 | 1] = Sum[r] - Sum[mid];
105         }
106         tag[o << 1] = tag[o << 1 | 1] = tag[o];
107         tag[o] = -1;
108     }
109     return;
110 }
111 
112 void Add(int L, int R, int l, int r, int o) {
113     if(L <= l && r <= R) {
114         sum[o] = Sum[r] - Sum[l - 1];
115         tag[o] = 1;
116         return;
117     }
118     int mid = (l + r) >> 1;
119     pushdown(l, r, o);
120     if(L <= mid) Add(L, R, l, mid, o << 1);
121     if(mid < R) Add(L, R, mid + 1, r, o << 1 | 1);
122     sum[o] = sum[o << 1] + sum[o << 1 | 1];
123     return;
124 }
125 
126 LL ask(int L, int R, int l, int r, int o) {
127     if(L <= l && r <= R) {
128         return sum[o];
129     }
130     int mid = (l + r) >> 1;
131     pushdown(l, r, o);
132     LL ans = 0;
133     if(L <= mid) {
134         ans += ask(L, R, l, mid, o << 1);
135     }
136     if(mid < R) {
137         ans += ask(L, R, mid + 1, r, o << 1 | 1);
138     }
139     return ans;
140 }
141 
142 inline void Add(int x, int y) {
143     while(top[x] != top[y]) {
144         if(deep[top[x]] > deep[top[y]]) {
145             std::swap(x, y);
146         }
147         Add(pos[top[y]], pos[y], 1, n, 1);
148         y = fa[top[y]];
149     }
150     if(deep[x] > deep[y]) std::swap(x, y);
151     if(x != y) Add(pos[x] + 1, pos[y], 1, n, 1);
152     return;
153 }
154 
155 inline LL ask(int x, int y) {
156     LL ans = 0;
157     while(top[x] != top[y]) {
158         if(deep[top[x]] > deep[top[y]]) {
159             std::swap(x, y);
160         }
161         ans += ask(pos[top[y]], pos[y], 1, n, 1);
162         y = fa[top[y]];
163     }
164     if(deep[x] > deep[y]) std::swap(x, y);
165     if(x != y) ans += ask(pos[x] + 1, pos[y], 1, n, 1);
166     return ans;
167 }
168 
169 inline void clear() {
170     memset(e + 1, 0, n * sizeof(int));
171     memset(son + 1, 0, n * sizeof(int));
172     tp = 0;
173     num = 0;
174     return;
175 }
176 /*
177 1
178 5
179 1 2 1
180 2 3 3
181 3 4 3
182 1 5 9
183 2
184 1 5 5
185 2 3 8
186 */
187 
188 namespace Line {
189     LL ta[N], ta2[N];
190     inline LL ask(int i) {
191         LL ans = -INF;
192         for(; i; i -= i & (-i)) {
193             ans = std::max(ans, ta[i]);
194         }
195         return ans;
196     }
197     inline void Add(int i, LL v) {
198         for(; i <= n; i += i & (-i)) {
199             ta[i] = std::max(ta[i], v);
200         }
201         return;
202     }
203     inline LL ask2(int i) {
204         LL ans = -INF;
205         for(; i; i -= i & (-i)) {
206             ans = std::max(ans, ta2[i]);
207         }
208         return ans;
209     }
210     inline void Add2(int i, LL v) {
211         for(; i <= n; i += i & (-i)) {
212             ta2[i] = std::max(ta2[i], v);
213         }
214         return;
215     }
216     inline void solve() {
217         for(int i = 1; i <= n; i++) ta2[i] = ta[i] = -INF;
218         LL ans = -INF;
219         std::sort(node + 1, node + m + 1);
220         for(int i = m; i >= 1; i--) {
221             LL temp = ask(node[i].y - 1);
222             if(temp != -INF) {
223                 ans = std::max(ans, temp + node[i].val - Sum[node[i].y]);
224             }
225             temp = ask2(node[i].y);
226             if(temp != -INF) {
227                 ans = std::max(ans, temp + node[i].val);
228             }
229             Add(node[i].x, node[i].val + Sum[node[i].x]);
230             Add2(node[i].y, node[i].val + Sum[node[i].x] - Sum[node[i].y]);
231         }
232         if(ans == -INF) puts("F");
233         else {
234             printf("%lld\n", ans);
235         }
236         clear();
237         return;
238     }
239 }
240 /*
241 50
242 2
243 1 2 914572059
244 3
245 1 2 213930211
246 1 2 0
247 2 2 0
248 */
249 inline void solve() {
250 
251     sum[1] = tag[1] = 0;
252 
253     scanf("%d", &n);
254     LL z;
255     bool FLAG = 1;
256     for(int i = 1, x, y; i < n; i++) {
257         scanf("%d%d%lld", &x, &y, &z);
258         add(x, y, z);
259         add(y, x, z);
260         if(y != x + 1) {
261             FLAG = 0;
262         }
263     }
264 
265     DFS_1(1, 0);
266     DFS_2(1, 1);
267 
268     for(int i = 1; i <= n; i++) {
269         Sum[i] += Sum[i - 1];
270     }
271 
272     scanf("%d", &m);
273     for(int i = 1; i <= m; i++) {
274         scanf("%d%d%lld", &node[i].x, &node[i].y, &node[i].z);
275         if(node[i].x > node[i].y) std::swap(node[i].x, node[i].y);
276         else if(node[i].x == node[i].y) {
277             m--;
278             i--;
279         }
280         node[i].val = dis(node[i].x, node[i].y) - node[i].z;
281         //printf("node %d [%d %d] val = %lld \n", i, node[i].x, node[i].y, node[i].val);
282     }
283     // solve
284     if(FLAG) {
285         Line::solve();
286         return;
287     }
288 
289     if(m > 300) {
290         clear();
291         return;
292     }
293 
294     LL ans = -INF;
295     for(int i = 1; i < m; i++) {
296         Add(node[i].x, node[i].y);
297         for(int j = i + 1; j <= m; j++) {
298             /// choose i j
299             LL Val = ask(node[j].x, node[j].y);
300             //printf("Val = %lld \n", Val);
301             if(Val) {
302                 ans = std::max(ans, node[i].val + node[j].val - Val);
303             }
304         }
305         tag[1] = sum[1] = 0;
306     }
307     if(ans == -INF) {
308         puts("F");
309     }
310     else {
311         printf("%lld\n", ans);
312     }
313     clear();
314     return;
315 }
316 
317 int main() {
318 
319     int T;
320     scanf("%d", &T);
321     while(T--) solve();
322     return 0;
323 }
30分代码

猜你喜欢

转载自www.cnblogs.com/huyufeifei/p/10679339.html