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