洛谷P4115 Qtree4
? 解题记录 ? ? 洛谷 ? ? 点分治 ? ? 点分树 ? ? 堆 ?    2018-05-26 22:06:41    533    0    0

题目描述

给出一棵边带权的节点数量为n的树,初始树上所有节点都是白色。有两种操作:

C x,改变节点x的颜色,即白变黑,黑变白

A,询问树中最远的两个白色节点的距离,这两个白色节点可以重合(此时距离为0)。

输入输出格式

输入格式:

 

In the first line there is an integer N (N <= 100000)

In the next N-1 lines, the i-th line describes the i-th edge: a line with three integers a b c denotes an edge between a, b of value c (-1000 <= c <= 1000)

In the next line, there is an integer Q denotes the number of instructions (Q <= 200000)

In the next Q lines, each line contains an instruction "C a" or "A"

 

输出格式:

 

For each "A" operation, write one integer representing its result. If there is no white node in the tree, you should write "They have disappeared.".

 

输入输出样例

输入样例#1: 复制
3
1 2 1
1 3 1
7
A
C 1
A
C 2
A
C 3
A
输出样例#1: 复制
2
2
0
They have disappeared.

第一次见这个题应该是在半年前了,外出集训看到这道题,根本不知所措。今天终于把这坑了半年的题填了。

#include<cstdio>
#include<algorithm>
#include<iostream>
#include<queue>
using namespace std;
const int maxn = 1e5 + 5;
const int inf = 0x3f3f3f3f;
struct edge {
    int v, w, next;
}e[maxn << 1];
int head[maxn], cnt, tot, ans;
void adde(const int &u, const int &v, const int &w) {
    e[++cnt] = (edge) {v, w, head[u]};
    head[u] = cnt;
}

struct Heap {
    priority_queue<int > M, D;
    void push(int x) {M.push(x);}
    void del(int x) {D.push(x);}
    void pop() {
        while(!M.empty() && !D.empty() && M.top() == D.top())
            M.pop(), D.pop();
        M.pop();
    }
    int top() {
        while(!M.empty() && !D.empty() && M.top() == D.top())
            M.pop(), D.pop();
        return M.empty() ? -inf : M.top();
    }
    int Qms() {
        int mx1 = top(), mx2, ans;
        if(mx1 == -inf) return 0;
        pop(), mx2 = top();
        if(mx2 == -inf) return push(mx1), 0;
        return push(mx1), mx1 + mx2;
    }
} Ans[maxn], Nd[maxn], All;

int size[maxn], mx[maxn], G, vis[maxn];
void FG(int u, int f, int & G, int tot) {
    size[u] = 1, mx[u] = 0;
    for(register int i = head[u]; i; i = e[i].next) {
        int v = e[i].v;
        if(vis[v] || v == f) continue;
        FG(v, u, G, tot), size[u] += size[v];
        mx[u] = max(mx[u], size[v]);
    }
    mx[u] = max(mx[u], tot - size[u]);
    if(mx[u] < mx[G]) G = u;
}

int LG[maxn], fa[maxn], lyr[maxn], Dp[maxn][22], Tp[maxn], Ap[maxn];

void GetInit(int u, int f, int G, int L, int w) {
    size[u] = 1;
    Dp[u][L] = w, Nd[G].push(w);
    for(register int i = head[u]; i; i = e[i].next) {
        int v = e[i].v;
        if(vis[v] || v == f) continue;
        GetInit(v, u, G, L, w + e[i].w);
        size[u] += size[v];
    }
}

void solve(int u, int rt, int L, int fw) {
    int v, tmp;
    GetInit(rt, 0, u, L, fw), vis[u] = 1, lyr[u] = L;
    for(register int i = head[u]; i; i = e[i].next) {
        v = e[i].v;
        if(vis[v]) continue;
        G = 0, FG(v, 0, G, size[v]), tmp = G;
        fa[G] = u, solve(G, v, L + 1, e[i].w);
        Tp[tmp] = Nd[tmp].top();
        Ans[u].push(Tp[tmp]);
    }
    Ans[u].push(0);
    All.push(Ap[u] = Ans[u].Qms());
}

void CG(int u) {
    if(!LG[u]) ++tot, LG[u] = 1, Ans[u].del(0);
    else --tot, LG[u] = 0, Ans[u].push(0);
    int tmp, p = u, as = Ans[u].Qms(), fp = fa[p];
    if(Ap[u] != as) All.push(as), All.del(Ap[u]), Ap[u] = as;
    while(fp) {
        if(!LG[u]) Nd[p].push(Dp[u][lyr[p]]);
        else Nd[p].del(Dp[u][lyr[p]]);
        tmp = Nd[p].top();
        if(Tp[p] != tmp) {
            if(Tp[p] != -inf) {Ans[fp].del(Tp[p]);}
            if(tmp != -inf) {Ans[fp].push(tmp);}
            Tp[p] = tmp;
        }
        as = Ans[fp].Qms();
        if(Ap[fp] != as)
            All.push(as), All.del(Ap[fp]), Ap[fp] = as;
        p = fa[p], fp = fa[p];
    }
}

char s[3];
int n, m, u, v, w, root;

int main() {
    mx[0] = inf;
    scanf("%d", &n);
    for(register int i = 1; i < n; ++i)
        scanf("%d%d%d", &u, &v, &w), adde(u, v, w), adde(v, u, w);
    G = 0, FG(1, 0, G, n), root = G;
    solve(G, 1, 0, 0);
    scanf("%d", &m);
    for(register int i = 1; i <= m; ++i) {
        scanf("%s", s);
        if(s[0] == 'A') 
            if(tot != n) printf("%d\n", All.top());
            else printf("They have disappeared.\n");
        else scanf("%d", &u), CG(u);
    }
    return 0;
}

 

上一篇: 为各位的博客提供雪花模板

下一篇: 洛谷P2056 [ZJOI2007]捉迷藏

533 人读过
立即登录, 发表评论.
没有帐号? 立即注册
0 条评论
文档导航