Bzoj3720 gty's sister tree Solution

Source: Internet
Author: User

Question:

Maintain a root tree with N nodes (the root node is 1) and the node number on the tree is 1-N. Each vertex has a weight WI.


The following operations are supported:

0 u x: the number of values strictly greater than X in the subtree rooted in U. (U ^ = lastans, x ^ = lastans)

1 u x changes the weight of the U node to X. (U ^ = lastans, x ^ = lastans)

2 u x: Add a node numbered "number of nodes in the current tree + 1". Its parent node is u and its weight is X. (U ^ = lastans, x ^ = lastans)

At the beginning, lastans = 0.

Idea: At first we can see that the query is related to the subtree, and we need to support dynamic addition. We want to dynamically maintain the DFS sequence. However, when the K-digit range is large, the splay will be grayed out.

And the offline tree structure won't work either.

So I think it is not feasible.

However, if this is a tree, how can we partition it?


We use a DFS process to split the tree.

First, define the root node in Block 1, and the size of Block 1 is 1.

From the root node down to DFS, for the current point X, traverse his son in sequence. If the size of the block where X is located is smaller than maxsize when traversing son, add son to the block where X is located, size of the block where X is located + 1.

Otherwise, create a new block and add son to the new block. The size of the new block is greater than 1.

Each time a son is traversed, the data is directed down to DFS.


Then we record two graphs. One is the original tree, and the other is the graph formed between blocks. You only need to add an edge each time a new block is generated.

It is not difficult to find that blocks and blocks form a tree structure.

We record and sort all the weights in each block.


For inquiry, we will go down to DFS from the current node. If a son does not belong to its block, we will go to the tree formed between the block and the block for downward search, every time you encounter a block, you can find the answer in the block. If the son still belongs to this block, check the relationship between him and X. For maxsize = SQRT (n), the complexity is O (SQRT (n) log (SQRT (n ))).

To add a new vertex, we can add a vertex directly to the block where the father is located. We need to modify the ordered sequence of the weight, complexity O (SQRT (n )). of course, if the size of the block where the father is located reaches maxsize, create a new block with one vertex.

If you modify the weight value, you can delete it directly in the weight sequence of the block where the point is located, and insert it. The time complexity is O (SQRT (n )).


In fact, maxsize = SQRT (n) logn may be faster? But I'm not...


Code:

#include <cmath>#include <cctype>#include <cstdio>#include <cstring>#include <algorithm>using namespace std; inline int getc() {    static const int L = 1 << 15;    static char buf[L], *S = buf, *T = buf;    if (S == T) {        T = (S = buf) + fread(buf, 1, L, stdin);        if (S == T)            return EOF;    }    return *S++;}inline int getint() {    int c;    while(!isdigit(c = getc()));    int tmp = c - '0';    while(isdigit(c = getc()))        tmp = (tmp << 1) + (tmp << 3) + c - '0';    return tmp;} #define N 30010#define M 30010#define Num 5010#define Size 5010 struct Graph {    int head[N + M], next[(N + M)<<1], end[(N + M)<<1], ind;    void reset() {        ind = 0;        memset(head, -1, sizeof(head));    }    void addedge(int a, int b) {        int q = ind++;        end[q] = b;        next[q] = head[a];        head[a] = q;    }    void make(int a, int b) {        addedge(a, b);        addedge(b, a);    }}G; struct Lump {    int head[Num], next[Num << 1], end[Num << 1], ind;    void reset() {        ind = 0;        memset(head, -1, sizeof(head));    }    void addedge(int a, int b) {        int q = ind++;        end[q] = b;        next[q] = head[a];        head[a] = q;    }    void make(int a, int b) {        addedge(a, b);        addedge(b, a);    }}Lumps; int w[N + M]; int per, size[Num], sav[Num][Size], belong[N + M], cnt, pa[N + M];void dfs(int x, int fa) {    for(int j = G.head[x]; j != -1; j = G.next[j]) {        if (G.end[j] == fa)            continue;        pa[G.end[j]] = x;        if (size[belong[x]] == per) {            belong[G.end[j]] = ++cnt, sav[cnt][++size[cnt]] = w[G.end[j]];            Lumps.make(cnt, belong[x]);        }        else            belong[G.end[j]] = belong[x], sav[belong[x]][++size[belong[x]]] = w[G.end[j]];        dfs(G.end[j], x);    }} inline int ask_Big(int ins, int x) {    sav[ins][size[ins] + 1] = 1 << 30;    int L = 1, R = size[ins] + 1, mid;    while(L < R) {        mid = (L + R) >> 1;        if (sav[ins][mid] > x)            R = mid;        else            L = mid + 1;    }    return size[ins] + 1 - L;}inline int ask_Lump(int x, int fa, int val) {    int res = ask_Big(x, val);    for(int j = Lumps.head[x]; j != -1; j = Lumps.next[j]) {        if (Lumps.end[j] != fa)            res += ask_Lump(Lumps.end[j], x, val);    }    return res;}inline int ask(int x, int fa, int val) {    int res = w[x] > val ? 1 : 0;    for(int j = G.head[x]; j != -1; j = G.next[j]) {        if (G.end[j] != fa) {            if (belong[G.end[j]] != belong[x])                res += ask_Lump(belong[G.end[j]], belong[x], val);            else                res += ask(G.end[j], x, val);        }    }    return res;} void remove(int ins, int val) {    int i, j;    for(i = 1; i <= size[ins]; ++i)        if (sav[ins][i] == val)            break;    --size[ins];    for(j = i; j <= size[ins]; ++j)        sav[ins][j] = sav[ins][j + 1];}void insert(int ins, int val) {    int i, j;    for(i = 1; i <= size[ins]; ++i)        if (sav[ins][i] > val)            break;    ++size[ins];    for(j = size[ins]; j > i; --j)        sav[ins][j] = sav[ins][j - 1];    sav[ins][i] = val;} int main() {    int n = getint();         register int i;    int a, b;    G.reset();    for(i = 1; i < n; ++i) {        a = getint(), b = getint();        G.make(a, b);    }         for(i = 1; i <= n; ++i)        w[i] = getint();         per = (int)sqrt(n * log(n)/log(2));         Lumps.reset();    belong[1] = size[++cnt] = 1, sav[cnt][1] = w[1];    dfs(1, -1);         for(i = 1; i <= cnt; ++i)        sort(sav[i] + 1, sav[i] + size[i] + 1);         int Q, ope, lastans = 0;    Q = getint();    while(Q--) {        ope = getint(), a = getint(), b = getint();        a ^= lastans;        b ^= lastans;        if (!ope)            printf("%d\n", lastans = ask(a, pa[a], b));        else if (ope == 1) {            remove(belong[a], w[a]);            insert(belong[a], w[a] = b);        }        else {            w[++n] = b;            pa[n] = a;            if (size[belong[a]] == per) {                belong[n] = ++cnt;                size[cnt] = 1;                sav[cnt][1] = w[n];                G.make(a, n);                Lumps.make(belong[a], cnt);            }            else {                belong[n] = belong[a];                insert(belong[a], w[n]);                G.make(a, n);            }        }    }         return 0;}


Bzoj3720 gty's sister tree Solution

Contact Us

The content source of this page is from Internet, which doesn't represent Alibaba Cloud's opinion; products and services mentioned on that page don't have any relationship with Alibaba Cloud. If the content of the page makes you feel confusing, please write us an email, we will handle the problem within 5 days after receiving your email.

If you find any instances of plagiarism from the community, please send an email to: info-contact@alibabacloud.com and provide relevant evidence. A staff member will contact you within 5 working days.

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.