Tree chain split title

SPOJ - QTREE3 Query on a tree again!

Description

You are given a tree (an acyclic undirected connected graph) with N nodes. The tree nodes are numbered from 1 to N. In the start, the color of any node in the tree is white.

We will ask you to perfrom some instructions of the following form:

  • 0 i : change the color of the i-th node (from white to black, or from black to white);
    or
  • 1 v : ask for the id of the first black node on the path from node 1 to node v. if it doesn't exist, you may return -1 as its result.

Input

In the first line there are two integers N and Q.

In the next N-1 lines describe the edges in the tree: a line with two integers a bdenotes an edge between a and b.

The next Q lines contain instructions "0 i" or "1 v" (1 ≤ i, v ≤ N).

Output

For each "1 v" operation, write one integer representing its result.

Example

Input:

9 8
1 2
1 3
2 4
2 9
5 9
7 9
8 9
6 8
1 3
0 8
1 6
1 7
0 2
1 9
0 2
1 9 

Output:

-1
8
-1
2
-1

Constraints & Limits

There are 12 real input files.

For 1/3 of the test cases, N=5000, Q=400000.

For 1/3 of the test cases, N=10000, Q=300000.

For 1/3 of the test cases, N=100000, Q=100000.

answer

After the split tree chain, with a segment tree or tree-like array maintenance intervals and to find the nearest distance of 1 black dot that is greater than the minimum intervals and find the left point zero, for the tree line query, we left his son to priority access for Fenwick tree can cover half the minimum depth inquiry point

Code

Half + Fenwick tree

#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
vector<int> G[N];
int n, m;
int fa[N];
int son[N];
int sze[N];
int dep[N];
void dfs1(int u, int f) {
    sze[u] = 1;
    fa[u] = f;
    son[u] = 0;
    dep[u] = dep[f] + 1;
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (v == f) continue;
        dfs1(v, u);
        sze[u] += sze[v];
        if (sze[v] > sze[son[u]]) son[u] = v;
    }
}
int top[N];
int cnt;
int pos[N];
int mp[N];
void dfs2(int u, int f, int t) {
    top[u] = t;
    pos[u] = ++cnt;
    mp[cnt] = u;
    if (son[u]) dfs2(son[u], u, t);
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (v == f || v == son[u]) continue;
        dfs2(v, u, v);
    }
}
int a[N];
int d[N];
void update(int x, int v) {
    for (int i = x; i <= n; i += i & (-i)) d[i] += v;
}
int query(int x) {
    int ans = 0;
    for (int i = x; i; i -= i & (-i)) ans += d[i];
    return ans;
}
int calcans(int u) {
    int ans = 0;
    int res = -1;
    while (top[u] != top[1]) {
        if (query(pos[u]) - query(pos[top[u]] - 1) > 0) {
            int l = pos[top[u]], r = pos[u];
            int tl = l;
            while (l <= r) {
                int mid = (l + r) >> 1;
                if (query(mid) - query(tl - 1) > 0) {
                    r = mid - 1;
                    ans = mid;
                }
                else l = mid + 1;
            }
            if (ans) res = mp[ans];
        }
        u = fa[top[u]];
    }
    if (query(pos[u]) - query(pos[1] - 1) > 0) {
        int l = pos[1], r = pos[u];
        while (l <= r) {
            int mid = (l + r) >> 1;
            if (query(mid) > 0) {
                r = mid - 1;
                ans = mid;
            }
            else l = mid + 1;
        }
        if (ans) res = mp[ans];
    }
    return res;
}
int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            G[i].clear();
        }
        memset(d, 0, sizeof(d));
        memset(sze, 0, sizeof(sze));
        memset(a, 0, sizeof(a));
        for (int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }

        dep[0] = 0;
        dfs1(1, 0);
        cnt = 0;
        dfs2(1, 0, 1);

        int ch, k;
        for (int i = 1; i <= m; i++) {
            scanf("%d%d", &ch, &k);
            switch(ch) {
                case 1: printf("%d\n", calcans(k)); break;
                case 0: {
                    if (a[k] == 0) {
                        update(pos[k], 1);
                        a[k] = 1;
                    }
                    else {
                        update(pos[k], -1);
                        a[k] = 0;
                    }
                    break;
                }

            }
        }

    return 0;
}

Segment tree

#include <bits/stdc++.h>
#define lson (o << 1)
#define rson (o << 1 | 1)
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
vector<int> G[N];
int n, m;
int fa[N];
int son[N];
int sze[N];
int dep[N];
void dfs1(int u, int f) {
    sze[u] = 1;
    fa[u] = f;
    son[u] = 0;
    dep[u] = dep[f] + 1;
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (v == f) continue;
        dfs1(v, u);
        sze[u] += sze[v];
        if (sze[v] > sze[son[u]]) son[u] = v;
    }
}
int top[N];
int cnt;
int pos[N];
int mp[N];
void dfs2(int u, int f, int t) {
    top[u] = t;
    pos[u] = ++cnt;
    mp[cnt] = u;
    if (son[u]) dfs2(son[u], u, t);
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (v == f || v == son[u]) continue;
        dfs2(v, u, v);
    }
}
int a[N];
int sumv[N << 2];
void pushup(int o) {
    sumv[o] = sumv[lson] + sumv[rson];
}
void update(int o, int l, int r, int pos) {
    if (l == r) {
        sumv[o] = !sumv[o];
        return;
    }
    int mid = (l + r) >> 1;
    if (pos <= mid) update(lson, l, mid, pos);
    else update(rson, mid + 1, r, pos);
    pushup(o);
}
int query(int o, int l, int r, int ql, int qr) {
    if (sumv[o] == 0) return 0;
    if (l == r) return l;
    int mid = (l + r) >> 1;
    int ans = 0;
    if (ql <= mid) ans = query(lson, l, mid, ql, qr);
    if (ans) return ans;
    if (qr > mid) ans = query(rson, mid + 1, r, ql, qr);
    return ans;
}
int calcans(int u) {
    int ans;
    int res = -1;
    while (1) {
        ans = query(1, 1, n, pos[top[u]], pos[u]);
        if (ans) res = mp[ans];
        if (u == 1 || top[u] == 1) break;
        u = fa[top[u]];
    }
    return res;
}
int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
        scanf("%d%d", &n, &m);
        for (int i = 1; i <= n; i++) {
            G[i].clear();
        }
        memset(sumv, 0, sizeof(sumv));
        memset(sze, 0, sizeof(sze));
        memset(a, 0, sizeof(a));
        for (int i = 1; i < n; i++) {
            int u, v;
            scanf("%d%d", &u, &v);
            G[u].push_back(v);
            G[v].push_back(u);
        }

        dep[0] = 0;
        dfs1(1, 0);
        cnt = 0;
        dfs2(1, 0, 1);

        int ch, k;
        for (int i = 1; i <= m; i++) {
            scanf("%d%d", &ch, &k);
            switch(ch) {
                case 1: printf("%d\n", calcans(k)); break;
                case 0: {
                    update(1, 1, n, pos[k]);
                    break;
                }

            }
        }

    return 0;
}

BZOJ-2243 staining

Description

Given an n-nodes m and unrooted trees operations, there are two types the operation:

1, the node b on a path to all node points are dyed to C;

2, a node query to the number of color segments on the path node b (successive same color are considered the same segment),

Such as "112221" by three segments: "11", "222" and "a."

You are to write a program in order to complete this m operations.

Input

The first line contains two integers n and m, respectively, and operand nodes;

The second line contains n positive integer n nodes initial color

The following lines contains two integers x and y, x and y represent Between an undirected edges.

The following lines each describing one operation:

"C abc" indicates that this is a dyeing operation, all the points on the node b to a path node (including a and b) are dyed to C;

"Q ab" indicates that this operation is a query to ask a node to node B (including a and b) the number of color segments on the path.

Output

For each query operation, output one line answer.

Sample Input

6 5
2 2 1 2 1 1
1 2
1 3
2 4
2 5
2 6
Q 3 5
C 2 1 1
Q 3 5
C 5 1 2
Q 3 5

Sample Output

3
1
2

Hint

Number N <= 10 ^ 5, operands M <= 10 ^ 5, all colors and C is an integer between [0, 10 ^ 9].

answer

After maintaining the number of colors tree sectional segments of each section with segment tree, what the left and right end points of the color point is determined as to whether the color merge

Code

#include <bits/stdc++.h>
#define lson (o << 1)
#define rson (o << 1 | 1)
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
vector<int> G[N];
const ll inf = 1e9;
int n;
ll val[N];
int fa[N];
int son[N];
int sze[N];
int dep[N];
void dfs1(int u, int f) {
    sze[u] = 1;
    fa[u] = f;
    son[u] = 0;
    dep[u] = dep[f] + 1;
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (v == f) continue;
        dfs1(v, u);
        sze[u] += sze[v];
        if (sze[v] > sze[son[u]]) son[u] = v;
    }
}
int top[N];
int cnt;
int pos[N];
int a[N];
void dfs2(int u, int f, int t) {
    top[u] = t;
    pos[u] = ++cnt;
    a[cnt] = val[u];
    if (son[u]) dfs2(son[u], u, t);
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i];
        if (v == f || v == son[u]) continue;
        dfs2(v, u, v);
    }
}
ll sumv[N << 2];
ll cov[N << 2];
ll L[N << 2];
ll R[N << 2];
void pushup(int o) {
    L[o] = L[lson];
    R[o] = R[rson];
    if (R[lson] == L[rson]) {
        sumv[o] = sumv[lson] + sumv[rson] - 1;
    }
    else sumv[o] = sumv[lson] + sumv[rson];
}
void pushdown(int o, int l, int r) {
    if (cov[o]) {
        cov[lson] = cov[rson] = cov[o];
        sumv[lson] = sumv[rson] = 1;
        L[lson] = R[lson] = cov[o];
        L[rson] = R[rson] = cov[o];
        cov[o] = 0;
    }
}
void build(int o, int l, int r) {
    if (l == r) {
        sumv[o] = 1;
        cov[o] = 0;
        L[o] = R[o] = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(lson, l, mid); build(rson, mid + 1, r);
    pushup(o);
}
void update(int o, int l, int r, int ql, int qr, ll v) {
    if (ql <= l && r <= qr) {
        sumv[o] = 1;
        cov[o] = v;
        L[o] = R[o] = v;
        return;
    }
    int mid = (l + r) >> 1;
    pushdown(o, l, r);
    if (ql <= mid) update(lson, l, mid, ql, qr, v);
    if (qr > mid) update(rson, mid + 1, r, ql, qr, v);
    pushup(o);
}
ll query(int o, int l, int r, int ql, int qr) {
    if (ql == l && r == qr) {
        return sumv[o];
    }
    int mid = (l + r) >> 1;
    pushdown(o, l, r);
    if (qr <= mid) return query(lson, l, mid, ql, qr);
    else if (ql > mid) return query(rson, mid + 1, r, ql, qr);
    else {
        ll res = query(lson, l, mid, ql, mid) + query(rson, mid + 1, r, mid + 1, qr);
        if (R[lson] == L[rson]) return res - 1;
        else return res;
    }
}
ll querycor(int o, int l, int r, int pos) {
    if (l == r) {
        return L[o];
    }
    int mid = (l + r) >> 1;
    pushdown(o, l, r);
    if (pos <= mid) return querycor(lson, l, mid, pos);
    else return querycor(rson, mid + 1, r, pos);
}
ll calcsum(int u, int v) {
    ll ans = 0;
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        ans += query(1, 1, n, pos[top[u]], pos[u]);
        int tmp = top[u];
        u = fa[top[u]];
        if (querycor(1, 1, n, pos[tmp]) == querycor(1, 1, n, pos[u])) ans--;
    }
    if (dep[u] < dep[v]) swap(u, v);
    ans += query(1, 1, n, pos[v], pos[u]);
    return ans;
}
void update1(int u, int v, ll val) {
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        update(1, 1, n, pos[top[u]], pos[u], val);
        u = fa[top[u]];
    }
    if (dep[u] < dep[v]) swap(u, v);
    update(1, 1, n, pos[v], pos[u], val);
}
int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    scanf("%d", &n);
    int m; scanf("%d", &m);
    for (int i = 1; i <= n; i++) scanf("%lld", &val[i]);
    for (int i = 1; i < n; i++) {
        int u, v;
        scanf("%d%d", &u, &v);
        G[u].push_back(v);
        G[v].push_back(u);
    }

    dep[0] = 0;
    dfs1(1, 0);
    cnt = 0;
    dfs2(1, 0, 1);
    build(1, 1, n);

    char ch[10];
    for (int i = 1; i <= m; i++) {
        scanf("%s", ch);
        int l, r, k;
        ll v;
        switch(ch[0]) {
            case 'Q': scanf("%d%d", &l, &r); printf("%lld\n", calcsum(l, r)); break;
            case 'C': {
                scanf("%d%d%lld", &l, &r, &v);
                update1(l, r, v);
                break;
            }

        }
    }
    return 0;
}

BZOJ-2157 Tour

Description

Le Ray loyal to travel, this time he came to the city of T. T City is a water city, a total of N spots, will be connected by a bridge between some attractions. For the convenience of tourists arrive each attraction but in order to save costs, there is only one path between any two T City attractions. In other words, T city only N - 1 bridges. Ray found that the bridge can see some beautiful scenery, people feel good, but some muddy narrow bridge, annoying. So he gave every seat define a bridge valence w, that is to say, Ray after the bridge will increase the pleasure of w, which may be positive or may be negative. Sometimes, Ray look the same bridge mood will change. Now, Ray wants you to help him calculate the total pleasure of the attractions that can be obtained from u to v attractions. Sometimes, he wants to know the minimum degree of pleasure maximum pleasure a certain degree the most beautiful bridge on the road to offer, or certain of the worst road bridge provided.

Input

The first line of the input contains an integer N, T represents the number of the city's attractions. Attractions numbered 0 ... N - 1. Next, N - 1 lines of three integers u, v and w, expressed a u to v, so that the bridge Ray valence of w increases. No bridge is 1 ... N - 1. | W | <= 1000. N + 1 input from the first row contains an integer M, represents the number of operations Ray. Then there are M rows, each row describes an operation, the operation has the following five forms: C iw, Ray represents elapsed for the i-th bridge valence became w. N uv, Ray expressed pleasure for each degree through a bridge on the path u to v attractions have become the opposite of the original. SUM uv, indicating an inquiry of total pleasure obtained from attractions u to v. MAX uv, indicating an inquiry biggest pleasure of all the bridges on the sights from u to v in the path of a bridge has to offer. MIN uv, represents the smallest pleasure of asking all the bridges on the sights to v u from the path of a bridge has to offer. Test data to ensure that, at any time, after an absolute value of valence Ray for each bridge is 1,000 or less.

Output

For each query (operation S, MAX and MIN), the output of the answer.

Sample Input

3
0 1 1
1 2 2
8
SUM 0 2
MAX 0 2
N 0 1
SUM 0 2
MIN 0 2
C 1 3
SUM 0 2
MAX 0 2

Sample Output

3
2
1
-1
5
3

Hint

A total of 10 data for the first i (1 <= i <= 10) data, N = M = i * 2000.

answer

This question is to the right side, the right side for convenience we do not chain split tree, the right side will be a child node to each edge, the right point so that the root node is zero, then the normal cross-sectional tree, interval for taking Instead of the number of the operation, we will then take the maximum and minimum negative exchange it, and direct the interval negated.

#include <bits/stdc++.h>
#define lson (o << 1)
#define rson (o << 1 | 1)
using namespace std;
const int N = 1e5 + 10;
typedef long long ll;
struct node {
    int v, w;
    node(int v = 0, int w = 0): v(v), w(w) {}
};
vector<node> G[N];
const int inf = 1e9;
int n;
int val[N];
int fa[N];
int son[N];
int sze[N];
int dep[N];
void dfs1(int u, int f) {
    sze[u] = 1;
    fa[u] = f;
    son[u] = 0;
    dep[u] = dep[f] + 1;
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i].v;
        if (v == f) continue;
        val[v] = G[u][i].w;
        dfs1(v, u);
        sze[u] += sze[v];
        if (sze[v] > sze[son[u]]) {
            son[u] = v;
        }
    }
}
int top[N];
int cnt;
int pos[N];
int a[N];
void dfs2(int u, int f, int t) {
    top[u] = t;
    pos[u] = ++cnt;
    a[cnt] = val[u];
    if (son[u]) dfs2(son[u], u, t);
    for (int i = 0; i < G[u].size(); i++) {
        int v = G[u][i].v;
        if (v == f || v == son[u]) continue;
        dfs2(v, u, v);
    }
}
int sumv[N << 2];
int maxv[N << 2];
int minv[N << 2];
void pushup(int o) {
    sumv[o] = sumv[lson] + sumv[rson];
    maxv[o] = max(maxv[lson], maxv[rson]);
    minv[o] = min(minv[lson], minv[rson]);
}
int negv[N << 2];
void myswap(int x) {
    negv[x] ^= 1;
    swap(maxv[x], minv[x]);
    maxv[x] = -maxv[x];
    minv[x] = -minv[x];
    sumv[x] = -sumv[x];
}
void pushdown(int o, int l, int r) {
    if (negv[o]) {
        myswap(lson); myswap(rson);
        negv[o] = 0;
    }
}
void build(int o, int l, int r) {
    if (l == r) {
        sumv[o] = maxv[o] = minv[o] = a[l];
        return;
    }
    int mid = (l + r) >> 1;
    build(lson, l, mid); build(rson, mid + 1, r);
    pushup(o);
}
void update(int o, int l, int r, int pos, int v) {
    if (l == r) {
        sumv[o] = maxv[o] = minv[o] = v;
        return;
    }
    int mid = (l + r) >> 1;
    pushdown(o, l, r);
    if (pos <= mid) update(lson, l, mid, pos, v);
    else update(rson, mid + 1, r, pos, v);
    pushup(o);
}
void neg(int o, int l, int r, int ql, int qr) {
    if (ql > r || qr < l) return;
    if (ql <= l && r <= qr) {
        myswap(o);
        return;
    }
    int mid = (l + r) >> 1;
    pushdown(o, l, r);
    if (ql <= mid) neg(lson, l, mid, ql, qr);
    if (qr > mid) neg(rson, mid + 1, r, ql, qr);
    pushup(o);
}
int querysum(int o, int l, int r, int ql, int qr) {
    if (ql > r || qr < l) return 0;
    if (ql <= l && r <= qr) {
        return sumv[o];
    }
    int mid = (l + r) >> 1;
    int ans = 0;
    pushdown(o, l, r);
    if (ql <= mid) ans += querysum(lson, l, mid, ql, qr);
    if (qr > mid) ans += querysum(rson, mid + 1, r, ql, qr);
    return ans;
}
int querymax(int o, int l, int r, int ql, int qr) {
    if (ql > r || qr < l) return -inf;
    if (ql <= l && r <= qr) {
        return maxv[o];
    }
    int mid = (l + r) >> 1;
    int ans = -inf;
    pushdown(o, l, r);
    if (ql <= mid) ans = max(ans, querymax(lson, l, mid, ql, qr));
    if (qr > mid) ans = max(ans, querymax(rson, mid + 1, r, ql, qr));
    return ans;
}
int querymin(int o, int l, int r, int ql, int qr) {
    if (ql > r || qr < l) return inf;
    if (ql <= l && r <= qr) {
        return minv[o];
    }
    int mid = (l + r) >> 1;
    pushdown(o, l, r);
    int ans = inf;
    if (ql <= mid) ans = min(ans, querymin(lson, l, mid, ql, qr));
    if (qr > mid) ans = min(ans, querymin(rson, mid + 1, r, ql, qr));
    return ans;
}
int csum(int u, int v) {
    int ans = 0;
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        ans += querysum(1, 1, n, pos[top[u]], pos[u]);
        u = fa[top[u]];
    }
    if (dep[u] < dep[v]) swap(u, v);
    ans += querysum(1, 1, n, pos[v] + 1, pos[u]);
    return ans;
}
int cmax(int u, int v) {
    int ans = -inf;
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        ans = max(ans, querymax(1, 1, n, pos[top[u]], pos[u]));
        u = fa[top[u]];
    }
    if (dep[u] < dep[v]) swap(u, v);
    ans = max(ans, querymax(1, 1, n, pos[v] + 1, pos[u]));
    return ans;
}
int cmin(int u, int v) {
    int ans = inf;
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        ans = min(ans, querymin(1, 1, n, pos[top[u]], pos[u]));
        u = fa[top[u]];
    }
    if (dep[u] < dep[v]) swap(u, v);
    ans = min(ans, querymin(1, 1, n, pos[v] + 1, pos[u]));
    return ans;
}
void update1(int u, int v) {
    while (top[u] != top[v]) {
        if (dep[top[u]] < dep[top[v]]) swap(u, v);
        neg(1, 1, n, pos[top[u]], pos[u]);
        u = fa[top[u]];
    }
    if (dep[u] < dep[v]) swap(u, v);
    neg(1, 1, n, pos[v] + 1, pos[u]);
}
struct edge {
    int u, v;
} edge[N];
int main() {
    //freopen("in.txt", "r", stdin);
    //freopen("out.txt", "w", stdout);
    scanf("%d", &n);
    val[1] = 0;
    for (int i = 1; i < n; i++) {
        int u, v, w;
        scanf("%d%d%d", &u, &v, &w);
        u++; v++;
        G[u].push_back(node(v, w));
        G[v].push_back(node(u, w));
        edge[i].u = u;
        edge[i].v = v;
    }
    dep[0] = 0;
    dfs1(1, 0);
    cnt = 0;
    dfs2(1, 0, 1);
    build(1, 1, n);
    int m; scanf("%d", &m);
    char ch[10];
    for (int i = 1; i <= m; i++) {
        scanf("%s", ch);
        int x, y;
        scanf("%d%d", &x, &y);
        if (ch[0] == 'S') {
            x++, y++;
            printf("%d\n", csum(x, y));
        }
        else if (ch[0] == 'C') {
            int v = dep[edge[x].u] < dep[edge[x].v] ? edge[x].v : edge[x].u;
            update(1, 1, n, pos[v], y);
        }
        else if (ch[0] == 'N') {
            x++; y++;
            update1(x, y);
        }
        else if (ch[1] == 'A') {
            x++; y++;
            printf("%d\n", cmax(x, y));
        }
        else {
            x++; y++;
            printf("%d\n", cmin(x, y));
        }
    }
    return 0;
}

continue

Guess you like

Origin www.cnblogs.com/artoriax/p/11294098.html