UVA - 12424 Answering Queries on a Tree(十棵线段树的树链剖分)

You are given a tree with N nodes. The tree nodes are numbered from 1 to N and have colors C1, C2,
. . . , CN initially. You have to handle M instructions on the tree of the following forms:
• 0 u c: Change the color of node u to c.
• 1 u v: Output the maximum number of times a color appeared on the unique path from node u
to node v.
Input
The first line of input contains T (1 ≤ T ≤ 10) which is the number of test cases. The first line of each
test case contains two integers N and M (1 ≤ N, M ≤ 105
). Next line contains N space separated
integers C1, C2, . . . , CN (1 ≤ Ci ≤ 10) denoting the initial colors of the nodes. Each of the next N − 1
lines contain two integers a and b (1 ≤ a, b ≤ N and a ̸= b) meaning that there is an edge between
node a and node b. Each of the next M lines contains an instruction of one of the two forms described
above. For all the instructions: 1 ≤ u, v ≤ N and 1 ≤ c ≤ 10.
Output
For each of the second type instruction output the answer in one line.
Sample Input
2
5 6
3 2 1 2 3
1 2
2 3
2 4
1 5
1 3 5
0 1 1
0 2 1
1 3 5
0 2 4
1 2 4
2 1
5 6
1 2
1 2 2
Sample Output
2
3
1
1

 

题意:给你一颗树,树上的每个节点都有颜色,颜色编号在1-10之间,给出两种操作

操作一:将树上x点的颜色搞成val

操作二:求点u到点v路径上最多的颜色有几个

 

题解:颜色很少,所以不用树上莫队,可以建10棵线段树,如果一个点的颜色为ai,则在ai编号的线段树上该点为1,其他编号的树上该点为0

然后每次跑路径的时候跑十遍,记下路径和最大的一种颜色输出,就是答案了,emmm,真暴力啊QAQ

因为涉及到树上路径,所以树链剖分即可了

 

代码如下:

#include<cstdio>
#include<vector>
#include<cstring>
#include<iostream>
#include<algorithm>
#define lson root<<1
#define rson root<<1|1
using namespace std;

struct seg_tree
{
    struct node
    {
        int l,r,sum;
    } tr[400040];

    void push_up(int root)
    {
        tr[root].sum=tr[lson].sum+tr[rson].sum;
    }

    void build(int root,int l,int r)
    {
        if(l==r)
        {
            tr[root].l=l;
            tr[root].r=r;
            return ;
        }
        tr[root].l=l;
        tr[root].r=r;
        int mid=(l+r)>>1;
        build(lson,l,mid);
        build(rson,mid+1,r);
    }

    void update(int root,int pos,int val)
    {
        if(tr[root].l==pos&&tr[root].r==pos)
        {
            tr[root].sum=val;
            return ;
        }
        int mid=(tr[root].l+tr[root].r)>>1;
        if(pos<=mid)
        {
            update(lson,pos,val);
        }
        else
        {
            update(rson,pos,val);
        }
        push_up(root);
    }

    int query(int root,int l,int r)
    {
        if(tr[root].l==l&&tr[root].r==r)
        {
            return tr[root].sum;
        }
        int mid=(tr[root].l+tr[root].r)>>1;
        if(mid<l)
        {
            return query(rson,l,r);
        }
        else
        {
            if(mid>=r)
            {
                return query(lson,l,r);
            }
            else
            {
                return query(lson,l,mid)+query(rson,mid+1,r);
            }
        }
    }

    void dfs(int root,int l,int r)
    {
        if(l==r)
        {
            return ;
        }

        int mid=(l+r)>>1;
        dfs(lson,l,mid);
        dfs(rson,mid+1,r);
    }
} tree[11];

vector<int> g[100010];
int fa[100010],deep[100010],size[100010],son[100010],id[100010],c[100010],w[100010],top[100010],cnt;

void dfs1(int now,int f,int dep)
{
    fa[now]=f;
    deep[now]=dep;
    size[now]=1;
    int maxson=-1;
    for(int i=0; i<g[now].size(); i++)
    {
        if(g[now][i]==f)
        {
            continue;
        }
        dfs1(g[now][i],now,dep+1);
        size[now]+=size[g[now][i]];
        if(size[g[now][i]]>maxson)
        {
            maxson=size[g[now][i]];
            son[now]=g[now][i];
        }
    }
}

void dfs2(int now,int topf)
{
    id[now]=++cnt;
    w[cnt]=c[now];
    top[now]=topf;
    if(!son[now])
    {
        return ;
    }
    dfs2(son[now],topf);
    for(int i=0; i<g[now].size(); i++)
    {
        if(fa[now]==g[now][i]||g[now][i]==son[now])
        {
            continue;
        }
        dfs2(g[now][i],g[now][i]);
    }
}

void point_update(int u,int val)
{
    for(int i=1; i<=10; i++)
    {
        if(val==i)
        {
            tree[i].update(1,id[u],1);
        }
        else
        {
            tree[i].update(1,id[u],0);
        }
    }
}

int path_query(int u,int v,int val)
{
    int ans=0;
    while(top[u]!=top[v])
    {
        if(deep[top[u]]<deep[top[v]])
        {
            swap(u,v);
        }
        ans+=tree[val].query(1,id[top[u]],id[u]);
        u=fa[top[u]];
    }
    if(deep[u]>deep[v])
    {
        swap(u,v);
    }
    ans+=tree[val].query(1,id[u],id[v]);
    return ans;
}

int main()
{
    int t;
    scanf("%d",&t);
    while(t--)
    {
        int n,m;
        memset(tree,0,sizeof(tree));
        memset(fa,0,sizeof(fa));
        memset(son,0,sizeof(son));
        memset(deep,0,sizeof(deep));
        memset(size,0,sizeof(size));
        memset(id,0,sizeof(id));
        memset(c,0,sizeof(c));
        memset(w,0,sizeof(w));
        memset(top,0,sizeof(top));
        cnt=0;
        for(int i=1;i<=100000;i++)
        {
            g[i].clear();
        }
        scanf("%d%d",&n,&m);
        for(int i=1; i<=n; i++)
        {
            scanf("%d",&c[i]);
        }
        for(int i=1; i<n; i++)
        {
            int from,to;
            scanf("%d%d",&from,&to);
            g[from].push_back(to);
            g[to].push_back(from);
        }
        dfs1(1,0,1);
        dfs2(1,1);
        for(int i=1; i<=10; i++)
        {
            tree[i].build(1,1,n);
        }
        for(int i=1; i<=n; i++)
        {
            tree[w[i]].update(1,i,1);
        }
        for(int i=1; i<=m; i++)
        {
            int kd,l,r;
            scanf("%d%d%d",&kd,&l,&r);
            if(kd==1)
            {
                int ans=0;
                for(int j=1; j<=10; j++)
                {
                    ans=max(ans,path_query(l,r,j));
                }
                printf("%d\n",ans);
            }
            else
            {
                if(kd==0)
                {
                    point_update(l,r);
                }

            }
        }
    }

}

 

posted @ 2018-05-11 18:23  Styx-ferryman  阅读(166)  评论(0编辑  收藏  举报