"YQOI2019" lost city of defensive stars the day solution to a problem

The last question of the game, but did not seem to have any effect of the anti-AK.

As YQOI, it is no prefix looked dislike.

Split template tree chain problem? A bit like.

Subject to the effect

Given an initial state of the tree and each point (labeled or unlabeled), a status of each change point (inverted state), or inquiry into the tree all markers \ (u-> v \) Simple path and the shortest distance.

The following is the data range:

No brain violence

We take aim to spearhead the first four points.

\ (the n-, m \ Leq 200 \) , what does this mean?

Simulation directly in accordance with the meaning of problems, first find out \ (u-> v \) all points on the simple path and marked, then each point as the root node, find the nearest point has been marked, and this point is obviously the best record The answer can be accumulated.

Time complexity: \ (O (n-2M ^) \) desired Score: \ (20 \) .

However, because the data comparison water, let the first \ (7-8 \) points the whole two special constraints can get \ (30pts. \)

End violence

To solve the (n, m \ leq 200 \ ) \ point, we can see that the next data \ (the n-, m \ Leq 2000 \) .

We want to speak in plain \ (O (nm) \) complete answer within the time.

In the analysis, not difficult to find, for each time asking us to do \ (O (n) \) time complexity.

We enumerate each point on the chain, when the enumeration point \ (x \) when considering which ones have the shortest distance marker is to \ (x \) is.

That is easy to find and remove after site comprises adjacent points encompassed by its scope \ (X \) range point.

It can be understood:

FIG red circle point is the shortest distance to the chain \ (X \) .

Set \ (f [x] \) represented by \ (X \) for all markers root to \ (X \) distance, \ (NUM_X \) represented by \ (X \) is the subtree rooted number a marked transfer is obvious:

\[f[x]=num_y*val_{x,y}+\sum_{y\in son\{x\}}f[y].\]

The answer can be accumulated.

Time complexity \ (O (nm) \) , the desired score \ (40 \) .

Fixed sum chain

Here for specific constraints 2.

Not difficult to find, if asked \ (u-> v \) does not change, we only need to modify the update for each answer can be.

Modify the point \ (x \) , we need to quickly find \ (u-> v \) the nearest point on the path.

If \ (u \) for the root, then the point is we're looking for \ (LCA (the X-, v) \) .

Time complexity: \ (O (nlogn mlogn +) \) , the desired score: \ (30 \) .

Tree chain summation

Here for a particular constraint 1.

Tree devolved into a chain, as long as we can find the answer in this chain.

We might as well put the tree into a chain abstract series,

Inquiry \ (l-> r \) , we only required the \ (1-> l \) in the point \ (L \) distance and plus \ (r-> n \) in point \ (r \) distance and on the line.

Just to take into account the \ (L \) portion (the \ (R & lt \) portion empathy).

发现\ (dis (i, l) = dis (i, n) -dis (l, n) \) ,

When summed, \ (ANS = \ sum_ {I} = ^ LDIS. 1 (I, n-) -num_ {l-> DIS L} * (L, n-) \) .

Obviously \ (\ sum_ {i = 1 } ^ ldis (i, n) \) and \ (num_ {1-> l} \) can all be used to modify the data structures of certain single point to maintain the summation interval.

Then I sort of got the.

Time complexity: \ (O (nlogn mlogn +) \) , the desired score: \ (35 \) .

Offline practice without modification

Do it here, it will be some prospect of a solution.

Some will not find a lot of points 1 number of operations, as long as the violence reconstruction after each change, as long as we deal with inquiries section.

Consider optimization "end the violence", we find the time to deal with this violence is repeated every time accumulate a lot of points.

In fact, we can pre-violent direct when asked for the range.

Consider multiplier, provided \ (g [x] [j ] \) represents \ (X \) a \ (2 ^ j \) ancestor \ (F \) values removed \ (f [x] \) of the remaining value, \ (G [x] [J] \) represents the x ancestors to just that area with the distance to this chain.

Without considering modification, \ (F [X] \) can find out in advance.

From \ (X \) jump \ (X \) a \ (2 ^ j \) ancestor \ (ANC \) of the process, we just add tired \ (G [x] [j ] \) to, for the outside world, with \ (g [x] [j ] \) and deal with it.

Time complexity: \ (O (K (+ nlogn mlogn)) \) where \ (K \) is the number of modifications,

Expect Score: \ (60 \) (little cards often).

Part A

The request is assumed path \ (u, v \) a \ (the LCA (U, V) = LCA \) .

We consider \ (lca \) contribution to answer all the points in the sub-tree.

In front of us when it comes to the multiplication is no way to modify the point, where we try to split the tree chain.

We must first know the value maintained, may wish to set point has not been marked as an array \ (Tag [i] \) . Apparently

\[f[x]=\sum_{tag[i],LCA(x,i)==x}dep[i]-dep[x]=\sum_{tag[i],LCA(x,i)==x}dep[i]-num_i*dep[x].\]

Specific reference may tree chain moiety.

Obviously \ (\ sum_ {tag [i ], LCA (x,) == x} dep [i] \) and \ (num_i \) can be coupled with an Euler sequence data structure maintained.

This means that we can \ (logn \) is calculated within the time \ (f [the X-] \) .

Consider again the above mentioned multiplier to \ (G \) .

Here we set \ (g [x] \) represents \ (f [x] \) minus its heavy son of \ (f \) value.

Analyze each modification which point of time we need to update \ (g \) value.

FIG dashed line represents the light chain, the solid line represents the heavy chain.

Obviously those points red circle only need to update \ (g \) value.

These points are a point \ (x \) is \ (top [x] \) of the parent node, and easy to get this point there are \ (logn \) a, can be done to update.

After the update is complete, we try to find the answer.

Consider \ (u-> lca \) parts.

If \ (u \) to jump up \ (fa [top [u] ] \) , then our task is to accumulate and this part.

Easy to find when we jump to the point \ (x \) , we want to skip \ (Top [the X-] \) , will accumulate \ (x-> top [x] \) on which a chain \ (g \) value.

And from \ (top [x] \) jumps \ (fa [top [x] ] \) , the

Since \ (top [x] \) is a light Son, our answer should be accumulated \ (f [fa [top [ x]] - f [top [x]] - num_ {top [x]} * val_ {top [ x], fa [top [x ]]}. \)

We were happy to discover, use \ (f \) and \ (g \) can do all of the above operations.

Such time complexity is \ (O ((n-m +) log ^ 2N) \) . 3 may be too specific constraints.

Expect Score: \ (65 \) , with no brain violence can get \ (80pts \) .

Part B

Next we have to consider \ (lca \) part other than the point of all this part of the shortest distance along this chain is to \ (lca \) .

We may assume \ (lca \) a point outside of \ (the X-\) .

Obviously \ (dis (x, lca) = dep [x] + dep [lca] -2 * dep [LCA (x, lca)]. \)

Then this part of the answer is

\[\sum dep[x]+num*dep[lca]-2*\sum dep[LCA(x,lca)].\]

The first part is a good find, as to \ (\ sum dep [LCA ( x, lca)] \) In this section we still use a similar approach.

For convenience of description, it is assumed \ (LCA (x, lca) = Lca. \)

Jump up, we put before \ (g [x] \) values maintained changed to \ (NUM_X * DEP [the X-] \) .

We can still jump up in the same way.

\ (g [x] \) replaced the same here \ (f [x] \) should be replaced.

Just moved back to the map, we found that from \ (top [x] -> fa [top [x]] \) in the process, we have lost that \ (fa [top [x] ] \) of the sub-tree removing \ (top [x] \) in this part of the subtree.

So we accumulate the answer should be \ ((num_ {FA [Top [the X-]]} - {num_ Top [the X-]}) * DEP [FA [Top [the X-]] \) .

So this part of it done.

Time complexity: \ (O ((n-m +) 2N log ^) \) , the desired score \ (100 \) .

Summary

  • Due to that the need to modify the marked point, we consider the chain tree split.

  • Fenwick tree defines four (rows other data structure) \ (A, B, C, D \) .
    • \ (A_x \) represented by \ (x \) is the root of the subtree how many markers.
    • \ (B_X \) represented by \ (X \) is the subtree rooted and depth of all markers.
    • \ (C_x \) represented by \ (X \) is removed subtree rooted in the range of a weight markers son subtree rooted formed to \ (X \) distance and the.
    • \ (D_X \) represented by \ (X \) is the number of removed subtree rooted marker having a weight in the range son subtree rooted formed by multiplying \ (DEP [X] \) .
    • Expression into the words: \ (= NUM_X A_x, B_X = A_x DEP * [X], D_X = (A_x-A_ {Son [X]}) * DEP [X] \.)
    • Obviously for a modification, \ (A, B \) only modified once, \ (C, D \) To modify \ (logn \) times.
  • Define four functions \ (F_X, g_x, F_X, g_x \) (no maintenance)
    • \ (F_X \) represented by \ (X \) subtree rooted at all points to a particular \ (X \) of the distance. Obviously \ (f_x = B_x-A_x * dep_x. \)
    • \ (g_x \) represented by \ (X \) is removed subtree rooted in the range of a weight markers son subtree rooted formed to \ (X \) distance and the. Obviously \ (g_x = C_x. \)
    • \ (F_X \) represented by \ (X \) the number of all marked points is multiplied by the subtree rooted at \ (dep_x \) . Obviously \ (F_x = A_x * dep_x. \)
    • \ (G_x \) represented by \ (X \) is the number of removed subtree rooted marker having a weight in the range son subtree rooted formed by multiplying \ (DEP [X] \) . Obviously \ (G_x = D_x. \)
    • It can be found in the above each function can be at least \ (logN \) is determined within.
  • In \ (LCA \) within the sub-tree portion
    • If you want to \ (x \) jumps \ (fa_x \) , and \ (x \) is \ (fa_x \) heavy son, direct plus \ (g_x \) can be.
    • The face of a point on the chain, the father of all the points are the sons of heavy point, you can directly add \ (\ SUM g_x \) .
    • For on a chain \ (top \) point, it is the light of its father son, so we should add \ (fa_x F_ {} {-f_x-A_x the X-* val_, fa_x} \) .
    • It is noteworthy that, when you go from \ (u-> lca \) and \ (v-> lca \) after the dance through, we will add more than a \ (LCA F_ {} \) , so the answer should subtract \ ( LCA} {F_ \) , from \ (u, v \) at the start of jump up, we need to add \ (f_u, f_v \) , namely \ (u, v \) subtree part of its contribution to the answer .
  • In \ (LCA \) an outer portion
    • For the \ (LCA \) other than the portion, the shortest distance from each point to the chain is to \ (LCA \) .
    • We know from the front, the need to add the answer to \ (\ SUM DEP [the X-] + NUM * DEP [LCA] -2 * \ SUM DEP [Lca] \) .
    • I.e. \ (({B_ -B_ the root} {} LCA) + (the root} {A_ LCA -a_ {}) * DEP [LCA] -2 * \ SUM DEP [Lca] \) .
    • Processing \ (\ sum dep [Lca] \) , the notice \ (Lca \) is \ (lca \) to \ (root \) points on (roots), we still deal with methods from the previous \ (lca \) to \ (root \) path.
    • If you want to \ (x \) jumps \ (fa_x \) , and \ (F \) is \ (fa_x \) heavy son, direct plus \ (G_x \) can be.
    • The face of a point on the chain, the father of all the points are the sons of heavy point, you can directly add \ (\ SUM g_x \) .
    • For on a chain \ (top \) point, it is the light of its father son, so we should add \ (fa_x F_ {} {-F_x-A_x the X-* val_, fa_x} \) .
  • The above is probably thinking, should realize there are some specific details.

However, it should be noted that very many details of this question, the code requires a certain degree of difficulty.

Complete code:

#include<bits/stdc++.h>
#define LL long long
#define maxn 210000
using namespace std;
int n,m,tag[maxn],last[maxn],p,id[maxn],ID = 0;
int size[maxn],top[maxn],tail[maxn],fa[maxn],son[maxn],type;
LL Dep[maxn],dep[maxn];
LL ans = 0;
struct tree_array
{
    LL d[maxn];
    LL lowbit(LL x) {return x & (- x);}
    LL Insert(int x,LL val) {while(x <= n) {d[x] += val; x += lowbit(x);}}
    LL getsum(int x) {return x ? getsum(x - lowbit(x)) + d[x] : 0;}
    LL query(int l, int r) {if(l > r) swap(l, r); return getsum(r) - getsum(l - 1);}
}A,B,C,D;
struct edge
{
    int x, y, next;
    LL val;
    void Add_edge(int X, int Y, LL Val)
    {
        x = X; y = Y; val = Val;
        next = last[x]; last[x] = p;
    }
}e[maxn * 2];
LL getdis(int u, int v) {return abs(dep[u] - dep[v]);}
LL sumA(int x) {return A.query(id[x], id[x] + size[x] - 1);}
LL sumB(int x) {return B.query(id[x], id[x] + size[x] - 1);}
void init1(int x)
{
    size[x] = 1;
    for(int k = last[x]; k; k = e[k].next)
    if(e[k].y != fa[x])
    {
        int y = e[k].y; fa[y] = x;
        dep[y] = dep[x] + e[k].val;
        Dep[y] = Dep[x] + 1;
        init1(y);
        size[x] += size[y];
        if(size[y] > size[son[x]]) son[x] = y;
    }
}
void init2(int x)
{
    id[x] = ++ ID;
    if(son[fa[x]] == x) top[x] = top[fa[x]];
    else top[x] = x;
    if(son[x]) init2(son[x]);
    for(int k = last[x]; k; k = e[k].next)
    if(e[k].y != fa[x] && e[k].y != son[x])
    init2(e[k].y);
    if(!son[x]) tail[x] = x;
    else tail[x] = tail[son[x]];
}
int LCA(int u, int v)
{
    while(u != v)
    {
        if(Dep[top[u]] < Dep[top[v]]) swap(u, v);
        if(top[u] == top[v]) return Dep[u] < Dep[v] ? u : v;
        else u = fa[top[u]];
    }
    return u;
}
void modify(int x)
{
    tag[x] ^= 1; LL flag = tag[x] * 2 - 1;
    int pos = x;
    A.Insert(id[x], flag);
    B.Insert(id[x], flag * dep[x]);
    while(x)
    {       
        C.Insert(id[x], flag * getdis(pos, x));
        D.Insert(id[x], flag * dep[x]);
        x = fa[top[x]];
    }
}
LL getF(int x) {return abs(sumB(x) - dep[x] * sumA(x));}
void findsum(int x, int anc)
{
    ans += getF(x);
    while(x != anc)
    {
        if(top[x] == top[anc]) {ans += C.query(id[fa[x]], id[anc]); return;}
        else 
        { 
            if(x == top[x]) 
            ans += getF(fa[x]) - getF(x) - sumA(x) * getdis(x, fa[x]);
            else
            {
                ans += getF(fa[top[x]]) - getF(top[x]) - sumA(top[x]) * getdis(top[x], fa[top[x]]);
                ans += C.query(id[fa[x]], id[top[x]]);
            }
            x = fa[top[x]];
        }
    }
}

void Sumlink(int x)
{
    while(x != 1)
    {
        if(top[x] == 1) {ans -= 2 * D.query(id[fa[x]], id[1]); break;}
        else
        {
            if(x == top[x]) {ans -= 2 * ((sumA(fa[x]) - sumA(x)) * dep[fa[x]]);}
            else {
            ans -= 2 * D.query(id[fa[x]], id[top[fa[x]]]);
            ans -= 2 * ((sumA(fa[top[x]]) - sumA(top[x])) * dep[fa[top[x]]]);
            }
            x = fa[top[x]];
        }
    }
}
LL query(int x,int y)
{
    int lca = LCA(x, y); ans = 0;
    findsum(x, lca); 
    findsum(y, lca);
    ans -= getF(lca);
    if(lca != 1)
    {
        ans += sumB(1) - sumB(lca) + (sumA(1) - sumA(lca)) * dep[lca];
        Sumlink(lca);
    } 
    return ans; 
}
int main()
{
    scanf("%d%d%d", &n, &m, &type); 
    for(int i = 1;i <= n - 1;i ++)
    {
        int u,v;LL w; scanf("%d%d%lld", &u, &v, &w);
        e[++ p].Add_edge(u, v, w);
        e[++ p].Add_edge(v, u, w);
    }
    init1(1); init2(1);
    for(int i = 1;i <= n;i ++)
    {
        int opt; scanf("%d", &opt);
        if(opt) modify(i);
    }
    for(int i = 1;i <= m;i ++)
    {
        int opt, x, y;
        scanf("%d%d", &opt, &x);
        if(opt == 2) scanf("%d", &y);
        if(opt == 1) modify(x);
        else printf("%lld\n", query(x, y));
    }
}

Remember to open the \ (long long \) Oh.

Guess you like

Origin www.cnblogs.com/dwqhca/p/11412064.html