Luogu P4175 [CTSC2008] Network Management Network

Topic description

Company M is a very large multinational company with branches or departments in many countries. In order to allow N departments distributed around the world to work together, the company has built a communication network that connects the entire company. The structure of the network consists of N routers and N-1 high-speed optical cables. Each department has a dedicated router, and all machines in the department's local area network are connected to this router, and then communicate with other departments through this communication subnet. This network structure guarantees that a direct or indirect path exists between any two routers in the network for communication. The data transmission speed of high-speed fiber optic cable is so fast that the delay time of transmission using fiber optic cable is negligible. However, due to aging routers, data exchange on these routers will bring a large delay. The communication delay time between two routers is related to the maximum switching delay time among all routers in the communication path of the two routers. As an intern in the network department of M company, you are now asked to write a simple program to monitor the company's network conditions. The program can update the change information of the network condition (the change of the delay time of router data exchange) at any time, and according to the inquiry, it can give the delay time of the router with the kth largest delay on the communication path of the two routers.

[Task] Your program reads from the input file the connection information of N routers and N-1 optical cables, the initial data exchange delay time Ti of each router, and Q pieces of query (or state change) information. And process these Q pieces of inquiry information in turn, they may be:

  1. The data exchange delay time of a router has changed due to an updated device or a new failure of the device.

  2. Query the delay time of the router with the kth largest delay on the path between two routers a and b.

Input and output format

Input format:

The first line contains two integers N and Q, representing the total number of routers and the total number of queries, respectively.

The second line contains N integers, and the ith number represents the initial data delay time Ti of the router numbered i.

Following N-1 lines, each line contains two integers x and y. Indicates that there is an optical cable connecting router x and router y.

This is followed by Q lines, each with three integers k, a, b.

If k=0, it means that the state of router a has changed, and its data exchange delay time is changed from Ta to b.

If k>0, it means to query the delay time of the router with the kth largest delay among all routers (including a and b) passed on the path from a to b. Note that a can be equal to b, in which case there is only one router on the path.

Output format:

For each second query (k > 0), print one line. Contains an integer for the corresponding delay time. If there are less than k routers on the path, the message "invalid request!" is output (all lowercase without quotation marks, and there is a space between two words).

Input and output example

Input Example #1:   Copy
5 5
5 1 2 3 4
3 1
2 1
4 3
5 3
2 4 5
0 1 2
2 2 3
2 1 4
3 3 5
Output Sample #1:   Copy
3
2
2
invalid request!

illustrate

The test data satisfies N, Q<=80000, and any router satisfies that the delay time is less than 10^8 at any time. 0<=K<=N is satisfied for all queries.


Solution

Brief meaning of the title: The path on the tree that supports point modification is the kth largest (not the kth in ascending order) query.

Consider these two issues separately. For the modification operation, we want to modify those weight segment trees of the entire subtree rooted with it. In the sequence operation, we often use BIT to cover , then consider converting the tree into a dfs sequence , so it becomes a sequence for interval operation, conventional difference .

For query operations, without modification, we can of course use v[x] + v[y] - v[lca(x, y)] - v[f[lca(x, y)]] as weights to run Chairman tree. Now it's just that every point is differentiated, so the prefix sum is what is required.

Compare and test code ability.

I will update this question laterViolenceTree chain segmentation + line segment tree set balanced tree solution!

Code

#include <cstdio>
#include <cstring>
#include <algorithm>
#define N 80010
#define M 8000010
using namespace std;
inline char gc() {
    static char now[1<<16], *S, *T;
    if(S == T) {T = (S = now) + fread(now, 1, 1<<16, stdin); if(S == T) return EOF;}
    return *S++;
}
inline int read() {
    int x = 0, f = 1; char c = gc();
    while(c < '0' || c > '9') {if(c == '-') f = -1; c = gc();}
    while(c >= '0' && c <= '9') {x = x * 10 + c - 48; c = gc();}
    return x * f;
}
struct edge {int to, next;}e[N<<1];
int a[N], head[N], f[N][17], b[N<<1], A[N], B[N], C[N], st[N], ed[N], root[N], dep[N], bit[N];
int L[M], R[M], v[M];
int n, q, cnt, m, dfn, len;
inline void ins(int x, int y) {e[++cnt].to = y; e[cnt].next = head[x]; head[x] = cnt;}
void add(int &now, int pre, int l, int r, int x, int k) {
    if(!now) now = ++len; v[now] = v[pre] + k;
    if(l == r) return ;
    int mid = (l + r)>>1;
    if(x <= mid) R[now] = R[pre], add(L[now], L[pre], l, mid, x, k);
    else L[now] = L[pre], add(R[now], R[pre], mid + 1, r, x, k);
}
void dfs(int x, int fa) {
    f[x][0] = fa; add(root[x], root[fa], 1, m, a[x], 1);
    st[x] = ++dfn;
    for(int i = head[x]; i; i = e[i].next) if(e[i].to != fa) dep[e[i].to] = dep[x] + 1, dfs(e[i].to, x);
    ed[x] = dfn;
}
inline void buildlca() {
    for(int j = 1; j < 17; ++j)
        for(int i = 1; i <= n; ++i) f[i][j] = f[f[i][j - 1]][j - 1];
}
inline int getlca(int x, int y) {
    if(dep[x] < dep[y]) swap(x, y);
    for(int i = 16; i >= 0; --i) if(dep[f[x][i]] >= dep[y]) x = f[x][i];
    if(x == y) return x;
    for(int i = 16; i >= 0; --i) if(f[x][i] != f[y][i]) x = f[x][i], y = f[y][i];
    return f[x][0];
}
int temp[N], c[N], d[N];
inline void bitup(int x, int pos, int k) {for(int i = x; i <= n; i+= i & -i) temp[i] = 0, add(temp[i], bit[i], 1, m, pos, k), bit[i] = temp[i];}
int numc, numd;
inline void get(int x, int p) {
    if(p == 0) {
        d[++numd] = root[x];
        x = st[x];
        for(; x; x-= x & -x) d[++numd] = bit[x];
    }else {
        c[++numc] = root[x];
        x = st[x];
        for(; x; x-= x & -x) c[++numc] = bit[x];
    }
}
inline int query(int k) {
    int l = 1, r = m, t, tt;
    while(l < r) {
        t = tt = 0;
        for(int i = 1; i <= numc; ++i) t+= v[R[c[i]]], tt+= v[c[i]];
        for(int i = 1; i <= numd; ++i) t-= v[R[d[i]]], tt-= v[d[i]];
        if(tt < k) return -1;
        if(k <= t) {
            for(int i = 1; i <= numc; ++i) c[i] = R[c[i]];
            for(int i = 1; i <= numd; ++i) d[i] = R[d[i]];
            l = ((l + r)>>1) + 1;
        }else {
            for(int i = 1; i <= numc; ++i) c[i] = L[c[i]];
            for(int i = 1; i <= numd; ++i) d[i] = L[d[i]];
            r = (l + r)>>1;
            k-= t;
        }
    }
    return l;
}
int main() {
    n = read(); q = read(); m = 0;
    for(int i = 1; i <= n; ++i) a[i] = read(), b[++m] = a[i];
    memset(head, 0, sizeof(head)); cnt = 1;
    for(int i = 1; i < n; ++i) {int x = read(), y = read(); ins(x, y); ins(y, x);}
    for(int i = 1; i <= q; ++i) {
        A[i] = read(); B[i] = read(); C[i] = read();
        if(!A[i]) b[++m] = C[i];
    }
    sort(b+1, b+m+1); m = unique(b+1, b+m+1) - b - 1;
    for(int i = 1; i <= n; ++i) a[i] = lower_bound(b+1, b+m+1, a[i]) - b;
    dfn = len = 0; dep[1] = 1; dfs(1, 0); buildlca();
    for(int i = 1; i <= n; ++i) bit[i] = root[0];
    for(int i = 1; i <= m; ++i) {
        int x = B[i], y = C[i];
        if(!A[i]) {
            y = lower_bound(b+1, b+m+1, y) - b;
            bitup(st[x], a[x], -1);
            bitup(ed[x] + 1, a[x], 1);
            bitup(st[x], y, 1);
            bitup(ed[x] + 1, y, -1);
            a[x] = y;
        }else {
            int z = getlca(x, y);
            numc = numd = 0;
            get(x, 1); get(y, 1); get(z, 0); get(f[z][0], 0);
            int ans = query(A[i]);
            if(ans == -1) puts("invalid request!");
            else printf("%d\n", b[ans]);
        }
    }
    return 0;
}

Guess you like

Origin http://43.154.161.224:23101/article/api/json?id=325833343&siteId=291194637