2013-team4/code/block-tree

从 Trac 迁移的文章

这是从旧校内 Wiki 迁移的文章,可能存在一些样式问题,您可以向 memset0 反馈。

原文章内容如下:

{{{
SPOJ QTREE
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1.

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

* CHANGE i ti : change the cost of the i-th edge to ti
* QUERY a b : ask for the maximum edge cost on the path from node a to node b
}}}

{{{
参考资料:http://hi.baidu.com/wjbzbmr/item/b17cb3bb06b4fc4a2bebe32a
块状树做法,将树分成sqrt{N}块,每块大小sqrt{N}
对于单点修改, 直接暴力在这个块中修改就可以了, 时间复杂度sqrt{N}
对于查询操作, 同一块中直接暴力查询,不同块就利用记录的信息跨块查询,时间复杂度sqrt{N}
}}}
{{{
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define PB push_back
#define MP make_pair

using namespace std;

typedef pair<int, int> PII;

const int MAXN=10005;
const int inf=100000000;

vector<PII> E[MAXN];
vector<int> ET[MAXN];
int to[MAXN], own[MAXN], fa[MAXN], dep[MAXN];
int size[MAXN], mm[MAXN], val[MAXN];
int edge[MAXN];
int L, N;

inline int get()
{
    char ch;
    while (ch=getchar(), (ch<'0'||ch>'9'));
    int ret=ch-'0';
    while (ch=getchar(), (ch>='0'&&ch<='9')) ret=ret*10+ch-'0';
    return ret;
}

void build(int u, int f, int d)
{
    dep[u]=d; fa[u]=f;
    int tmp=own[u];
    for (int i=0; i<E[u].size(); i++)
    {
        int v=E[u][i].first, id=E[u][i].second;
        if (v==f) continue;
        to[id]=v; val[v]=edge[id];
        if (size[tmp]<L) ET[u].PB(v), own[v]=tmp, size[tmp]++;
        build(v, u, d+1);

    }
}

void dfs(int u, int m)
{
    m=max(m, val[u]); mm[u]=m;
    for (int i=0; i<ET[u].size(); i++)
        dfs(ET[u][i], m);
}

void change(int id, int value)
{
    int u=to[id]; val[u]=value;
    if (own[u]==u) dfs(u, -inf);
    else dfs(u, mm[fa[u]]);
}

int query(int a, int b)
{
    int M=-inf;
    while (a!=b)
    {
        if (dep[a]<dep[b]) swap(a, b);
        if (own[a]==own[b]) M=max(M, val[a]), a=fa[a];
        else
        {
            if (dep[own[a]]<dep[own[b]]) swap(a, b);
            M=max(M, mm[a]); a=fa[own[a]];
        }
    }
    return M;
}

int main()
{
    int T=get();
    while (T--)
    {
        N=get(); L=sqrt(N)+1;
        for (int i=0; i<N; i++) E[i].clear(), ET[i].clear(), size[i]=0, own[i]=i;
        for (int u, v, w, i=1; i<N; i++)
        {
            u=get(); v=get(); w=get(); u--, v--;
            E[u].PB(MP(v, i)); E[v].PB(MP(u, i)); edge[i]=w;
        }
        build(0, -1, 0);
        for (int i=0; i<N; i++)
            if (own[i]==i) dfs(i, -inf);
        char st[100];
        while (scanf("%s", st)&&st[0]!='D')
        {
            int u, v;
            u=get(); v=get();
            if (st[0]=='C') change(u, v);
            else printf("%d\n", query(u-1, v-1));
        }
    }
    return 0;
}
}}}
SPOJ QTREE
You are given a tree (an acyclic undirected connected graph) with N nodes, and edges numbered 1, 2, 3...N-1.
We will ask you to perfrom some instructions of the following form:
* CHANGE i ti : change the cost of the i-th edge to ti
* QUERY a b : ask for the maximum edge cost on the path from node a to node b
参考资料:http://hi.baidu.com/wjbzbmr/item/b17cb3bb06b4fc4a2bebe32a
块状树做法,将树分成sqrt{N}块,每块大小sqrt{N}
对于单点修改, 直接暴力在这个块中修改就可以了, 时间复杂度sqrt{N}
对于查询操作, 同一块中直接暴力查询,不同块就利用记录的信息跨块查询,时间复杂度sqrt{N}
#include <cmath>
#include <vector>
#include <cstdio>
#include <cstring>
#include <cstdlib>
#include <algorithm>
#define PB push_back
#define MP make_pair
using namespace std;
typedef pair<int, int> PII;
const int MAXN=10005;
const int inf=100000000;
vector<PII> E[MAXN];
vector<int> ET[MAXN];
int to[MAXN], own[MAXN], fa[MAXN], dep[MAXN];
int size[MAXN], mm[MAXN], val[MAXN];
int edge[MAXN];
int L, N;
inline int get()
{
    char ch;
    while (ch=getchar(), (ch<'0'||ch>'9'));
    int ret=ch-'0';
    while (ch=getchar(), (ch>='0'&&ch<='9')) ret=ret*10+ch-'0';
    return ret;
}
void build(int u, int f, int d)
{
    dep[u]=d; fa[u]=f;
    int tmp=own[u];
    for (int i=0; i<E[u].size(); i++)
    {
        int v=E[u][i].first, id=E[u][i].second;
        if (v==f) continue;
        to[id]=v; val[v]=edge[id];
        if (size[tmp]<L) ET[u].PB(v), own[v]=tmp, size[tmp]++;
        build(v, u, d+1);
    }
}
void dfs(int u, int m)
{
    m=max(m, val[u]); mm[u]=m;
    for (int i=0; i<ET[u].size(); i++)
        dfs(ET[u][i], m);
}
void change(int id, int value)
{
    int u=to[id]; val[u]=value;
    if (own[u]==u) dfs(u, -inf);
    else dfs(u, mm[fa[u]]);
}
int query(int a, int b)
{
    int M=-inf;
    while (a!=b)
    {
        if (dep[a]<dep[b]) swap(a, b);
        if (own[a]==own[b]) M=max(M, val[a]), a=fa[a];
        else
        {
            if (dep[own[a]]<dep[own[b]]) swap(a, b);
            M=max(M, mm[a]); a=fa[own[a]];
        }
    }
    return M;
}
int main()
{
    int T=get();
    while (T--)
    {
        N=get(); L=sqrt(N)+1;
        for (int i=0; i<N; i++) E[i].clear(), ET[i].clear(), size[i]=0, own[i]=i;
        for (int u, v, w, i=1; i<N; i++)
        {
            u=get(); v=get(); w=get(); u--, v--;
            E[u].PB(MP(v, i)); E[v].PB(MP(u, i)); edge[i]=w;
        }
        build(0, -1, 0);
        for (int i=0; i<N; i++)
            if (own[i]==i) dfs(i, -inf);
        char st[100];
        while (scanf("%s", st)&&st[0]!='D')
        {
            int u, v;
            u=get(); v=get();
            if (st[0]=='C') change(u, v);
            else printf("%d\n", query(u-1, v-1));
        }
    }
    return 0;
}