Query on a tree(hdu 3804 树链剖分+线段树 vector)

Query on a tree

Time Limit: 15000/5000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)
Total Submission(s): 1298    Accepted Submission(s): 332



Problem Description
  There are some queries on a tree which has n nodes. Every query is described as two integers (X, Y).For each query, you should find the maximum weight of the edges in set E, which satisfies the following two conditions.
1) The edge must on the path from node X to node 1.
2) The edge’s weight should be lower or equal to Y.
  Now give you the tree and queries. Can you find out the answer for each query?
 

Input
  The first line of the input is an integer T, indicating the number of test cases. For each case, the first line contains an integer n indicates the number of nodes in the tree. Then n-1 lines follows, each line contains three integers X, Y, W indicate an edge between node X and node Y whose value is W. Then one line has one integer Q indicates the number of queries. In the next Q lines, each line contains two integers X and Y as said above.
 

Output
  For each test case, you should output Q lines. If no edge satisfy the conditions described above,just output “-1” for this query. Otherwise output the answer for this query.
 

Sample Input
 
 
1 3 1 2 7 2 3 5 4 3 10 3 7 3 6 3 4
 

Sample Output
 
 
7 7 5 -1
Hint
2<=n<=10^5 2<=Q<=10^5 1<=W,Y<=10^9 The data is guaranteed that your program will overflow if you use recursion.

题意:给定一棵树,树上每条边都有一个权值,给定x,y,问树的根(节点1)到节点x的路径中权值小于y的最大权值是多少,若没有,输出-1 。

思路:把边的信息和询问的信息都存下来,并把两者都按权值的大小排序(小->大),然后从询问里的最小的y开始,把边中权值小于y的边插入到线段树里,那么线段树只要维护区间的权值最大值即可。当然,一开始给的是一棵树,要先进行树链剖分。

#pragma comment(linker, "/STACK:10240000000000,10240000000000")
#include <iostream>
#include <cstdio>
#include <cstring>
#include <cmath>
#include <vector>
#include <queue>
#include <algorithm>
using namespace std;

const int MAX = 1e5+5;

typedef struct{
    int x,y;
    int val;
}Edge;

typedef struct{
    int x,y;
    int id;
}Query;

int n,q;
vector<int>map[MAX];
Edge edge[MAX];
Query query[MAX];
int ans[MAX];
//树链剖分
int cnt;
int siz[MAX],top[MAX],son[MAX],dep[MAX],faz[MAX],tid[MAX];
//线段树
int tree[MAX<<2];

bool cmp1(Edge a,Edge b)
{
    return a.val<b.val;
}

bool cmp2(Query a,Query b)
{
    return a.y<b.y;
}

//*********树链剖分*********

void dfs1(int root,int fa,int depth)
{
    siz[root]=1;
    faz[root]=fa;
    dep[root]=depth;
    son[root]=0;
    for(int i=0;i<map[root].size();i++)
    {
        if(map[root][i]==fa)
            continue;
        dfs1(map[root][i],root,depth+1);
        siz[root]+=siz[map[root][i]];
        if(siz[map[root][i]]>siz[son[root]])
            son[root]=map[root][i];
    }
}

void dfs2(int root,int tp)
{
    top[root]=tp;
    tid[root]=++cnt;
    if(son[root])
        dfs2(son[root],tp);
    for(int i=0;i<map[root].size();i++)
    {
        if(map[root][i]==son[root]||map[root][i]==faz[root])
            continue;
        dfs2(map[root][i],map[root][i]);
    }
}

//**************************

//**********线段树**********

void PushUp(int root)
{
    tree[root]=max(tree[root<<1],tree[root<<1|1]);
}

/*void build(int l,int r,int root)
{
    if(l==r)
    {
        tree[root]=0;
        return;
    }
    int mid=(l+r)>>1;
    build(l,mid,root<<1);
    build(mid+1,r,root<<1|1);
    PushUp(root);
}*/

void update(int x,int y,int l,int r,int root)
{
    if(l==r)
    {
        tree[root]=y;
        return;
    }
    int mid=(l+r)>>1;
    if(x<=mid)
        update(x,y,l,mid,root<<1);
    else
        update(x,y,mid+1,r,root<<1|1);
    PushUp(root);
}

int Query1(int L,int R,int l,int r,int root)
{
    if(L<=l&&r<=R)
    {
        return tree[root];
    }
    int mid=(l+r)>>1;
    int ans=0;
    if(L<=mid)
        ans=max(ans,Query1(L,R,l,mid,root<<1));
    if(R>mid)
        ans=max(ans,Query1(L,R,mid+1,r,root<<1|1));
    return ans;
}

//**************************

//基于树链的查询

int change(int x,int y)
{
    int ans=0;
    int f1=top[x];
    int f2=top[y];
    while(f1!=f2)
    {
        if(dep[f1]<dep[f2])
        {
            swap(x,y);
            swap(f1,f2);
        }

        ans=max(ans,Query1(tid[f1],tid[x],1,n,1));

        x=faz[f1];
        f1=top[x];
    }
    if(tid[x]>tid[y])
        swap(x,y);

    ans=max(ans,Query1(tid[x],tid[y],1,n,1));

    return ans;
}

int main()
{
    int T;
    scanf("%d",&T);
    while(T--)
    {
        memset(tree,0,sizeof(tree));
        scanf("%d",&n);
        for(int i=0;i<=n;i++)
            map[i].clear();
        for(int i=1;i<n;i++)
        {
            scanf("%d%d%d",&edge[i].x,&edge[i].y,&edge[i].val);
            map[edge[i].x].push_back(edge[i].y);
            map[edge[i].y].push_back(edge[i].x);
        }
        scanf("%d",&q);
        for(int i=1;i<=q;i++)
        {
            scanf("%d%d",&query[i].x,&query[i].y);
            query[i].id=i;
        }
        sort(edge+1,edge+n,cmp1);
        sort(query+1,query+q+1,cmp2);
        cnt=0;
        dfs1(1,0,1);
        dfs2(1,1);
        int k=1;
        for(int i=1;i<=q;i++)
        {
            for(;k<n;k++)
            {
                if(edge[k].val>query[i].y)
                    break;
                int c;
                if(dep[edge[k].x]>dep[edge[k].y])
                    c=edge[k].x;
                else
                    c=edge[k].y;
                update(tid[c],edge[k].val,1,n,1);
            }
            ans[query[i].id]=change(1,query[i].x);
        }
        for(int i=1;i<=q;i++)
            printf("%d\n",ans[i]==0?-1:ans[i]);
    }
    return 0;
}


  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值