Query on a tree
Time Limit: 15000/5000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1303 Accepted Submission(s): 334
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.
题意:
给你一棵树,和树上边的权值,在有q组询问a,b,问你从节点a->节点1的路径上,不小于b的最大的边的权值是多少,输出
解析:
一开始想到区间第k大的数问题上,用归并树做会MLE,所以就搜了题解
题解写的是一开始建一颗空树,然后记录每条边的权值,并按权值从小到大排序,先放在数组里,再记录所有的询问,每一个询问按照b值从小到大排序,
再每一次处理,就把<=b的边插入到线段树里面,在用树链剖分进行查询得到最大值
#include<cstdio>
#include<cstring>
#include<vector>
#include<algorithm>
using namespace std;
const int MAXN = 1e5+10;
typedef long long int lli;
#define INF 0x3f3f3f3f3f3f3f3f
#define M(a) memset(a,0,sizeof(a))
#define lson root<<1
#define rson root<<1|1
int fa[MAXN],dep[MAXN],siz[MAXN],id[MAXN],top[MAXN],ran[MAXN],son[MAXN];
typedef struct fc
{
int id;
lli w;
}fc;
fc val[MAXN];
typedef struct ee
{
int u,v;
int next;
lli w;
}ee;
ee edge[MAXN*2];
int head[MAXN],cnt;
int num,n;
typedef struct node
{
int l,r;
int val;
}node;
node Btree[MAXN*4];
lli d[MAXN*50];
int tot;
void addedge(int u,int v,lli cap)
{
edge[cnt].u=u;
edge[cnt].v=v;
edge[cnt].next=head[u];
edge[cnt].w=cap;
head[u]=cnt++;
}
void dfs1(int x,int f,int d)
{
dep[x]=d;
siz[x]=1;
son[x]=0;
fa[x]=f;
for(int i=head[x];i!=-1;i=edge[i].next)
{
int tmp=edge[i].v;
if(tmp==f) continue;
dfs1(tmp,x,d+1);
siz[x]+=siz[tmp];
if(siz[son[x]]<siz[tmp])
{
son[x]=tmp;
}
}
}
void dfs2(int x,int tp)
{
top[x]=tp;
id[x]=++num;
ran[num]=x;
if(son[x]) dfs2(son[x],tp);
for(int i=head[x];i!=-1;i=edge[i].next)
{
int tmp=edge[i].v;
if(tmp==fa[x]||tmp==son[x]) continue;
dfs2(tmp,tmp);
}
}
void build(int l,int r,int root)
{
if(l>r) return;
if(l==r)
{
Btree[root].l=l;
Btree[root].r=r;
Btree[root].val=0;
return;
}
int mid=(l+r)/2;
build(l,mid,root*2);
build(mid+1,r,root*2+1);
Btree[root].l=l;
Btree[root].r=r;
Btree[root].val=max(Btree[lson].val,Btree[rson].val);
}
void update(int root,int l,int r,int index,int val)
{
if(l>r) return;
if(l==r)
{
if(l==index)
{
Btree[root].val=val;
}
return;
}
int mid=(l+r)/2;
if(index<=mid)
update(root*2,l,mid,index,val);
else
update(root*2+1,mid+1,r,index,val);
Btree[root].val=max(Btree[lson].val,Btree[rson].val);
}
lli querysum(int root,int l,int r,int s,int e)
{
if(r<s||l>e)
{
return 0;
}
if(l>r) return 0;
if(s<=l&&r<=e)
{
return Btree[root].val;
}
int mid=(l+r)/2;
if(mid>=e) return querysum(2*root,l,mid,s,e);
else if(mid+1<=s) return querysum(root*2+1,mid+1,r,s,e);
else
{
return max(querysum(2*root,l,mid,s,e),querysum(root*2+1,mid+1,r,s,e));
}
}
/*********************前面就是简单的线段树求最大值的部分******/
lli solvesum(int a,int b,lli c)
{
if(dep[top[a]]<dep[top[b]])
{
swap(a,b);
}
lli ans=0;
while(top[a]!=top[b])
{
//int tmp=top[a];
ans=max(ans,querysum(1,1,n,id[top[a]],id[a]));
a=fa[top[a]];
if(dep[top[a]]<dep[top[b]])
{
swap(a,b);
}
}
if(id[a]>id[b]) swap(a,b);
ans=max(ans,querysum(1,1,n,id[a],id[b]));
if(ans==0) return -1;
else
return ans;
}
bool cmp1(fc a,fc b)
{
if(a.w==b.w) return a.id<b.id;
return a.w<b.w;
}
typedef struct qu
{
int ind;
lli w;
int id;
lli ans;
}qu;
qu ques[MAXN];
bool cmp2(qu a,qu b)
{
return a.w<b.w;
}
bool cmp3(qu a,qu b)
{
return a.id<b.id;
}
int main()
{
int q,t;
scanf("%d",&t);
while(t--)
{
scanf("%d",&n);
num=tot=0;
M(Btree);
M(son);
cnt=0;
memset(head,-1,sizeof(head));
for(int i=1;i<n;i++)
{
int u,v;
lli w;
scanf("%d%d%lld",&u,&v,&w);
addedge(u,v,w);
addedge(v,u,w);
}
dfs1(1,0,1);
dfs2(1,1);
for(int i=0;i<cnt;i+=2)
{
if(dep[edge[i].u]>dep[edge[i].v]) swap(edge[i].u,edge[i].v);
val[id[edge[i].v]].w=edge[i].w;
val[id[edge[i].v]].id=id[edge[i].v];
}
sort(val+2,val+n+1,cmp1);
int cm,a,b;
build(1,n,1);
scanf("%d",&q);
cm=2;
for(int i=0;i<q;i++)
{
scanf("%d%lld",&ques[i].ind,&ques[i].w);
ques[i].id=i;
}
sort(ques,ques+q,cmp2);
for(int i=0;i<q;i++)
{
int a=ques[i].ind;
lli b=ques[i].w;
while(val[cm].w<=b)
{
update(1,1,n,val[cm].id,val[cm].w);
cm++;
}
ques[i].ans=solvesum(a,1,b+1);
}
sort(ques,ques+q,cmp3);
for(int i=0;i<q;i++)
{
printf("%lld\n",ques[i].ans);
}
}
return 0;
}