Hdu 3804 Query on a tree 树链剖分+线段树

Query on a tree

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


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.
 

Author
Edward_mj
 

Source


给定一棵树,每条边有边权,询问每个点到1号节点路径上的所有边权中不超过y的最大值。


利用线段树,所有边权先设为负。

把边和询问按权值排序,保证每次查询之前所有比限制的最大边权大的边都没有在线段树中更新,这样就可以直接在线段树当中查询最大值。


代码长得可怕,3540B。


#include <cstdio>
#include <iostream>
#include <string.h>
#include <string> 
#include <map>
#include <queue>
#include <vector>
#include <set>
#include <algorithm>
#include <math.h>
#include <cmath>
#include <stack>
#define mem0(a) memset(a,0,sizeof(a))
#define meminf(a) memset(a,0x3f,sizeof(a))
using namespace std;
typedef long long ll;
typedef long double ld;
const int maxn=100001,inf=0x3f3f3f3f;  
const ll llinf=0x3f3f3f3f3f3f3f3f;   
const ld pi=acos(-1.0L);
int size[maxn],son[maxn],fa[maxn],top[maxn],dep[maxn],dfn[maxn];
int ans[maxn];
bool visit[maxn];
int num;
vector<int> v[maxn];

struct Mayer{
	int x,y,d;
};
Mayer a[maxn];

bool cmp(Mayer a,Mayer b) {
	return a.d<b.d;
}

struct query {
	int x,y,id;
};
query q[maxn];

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

void addedge(int from,int to) {
	v[from].push_back(to);
	v[to].push_back(from);
}

int dfs(int now,int step) {
	visit[now]=1;son[now]=-1;dep[now]=step;size[now]=1;
	for (int i=0;i<v[now].size();i++) {
		int to=v[now][i];
		if (!visit[to]) {
			fa[to]=now;
			size[now]+=dfs(to,step+1);
			if (son[now]==-1||size[to]>size[son[now]]) son[now]=to;
		}
	}
	return size[now];
}

void dfs2(int now,int t) {
	visit[now]=1;top[now]=t;dfn[now]=++num;
	if (son[now]!=-1) dfs2(son[now],t);
	for (int i=0;i<v[now].size();i++) {
		int to=v[now][i];
		if (!visit[to]) 
			dfs2(to,to);
	}
}

struct Tree {
	int l,r,lc,rc,max;
};
Tree tree[4*maxn];

void build(int now,int l,int r) {
	tree[now].l=l;tree[now].r=r;
	if (l==r) {
		tree[now].max=-1;
	} else {
		num++;
		tree[now].lc=num;
		build(num,l,(l+r)/2);
		num++;
		tree[now].rc=num;
		build(num,(l+r)/2+1,r);
		tree[now].max=max(tree[tree[now].lc].max,tree[tree[now].rc].max);
	}
}

void update(int now,int pos,int val) {
//	cout << tree[now].l << ' ' << tree[now].r << ' ' << tree[now].max << endl;
	if (tree[now].l==tree[now].r&&tree[now].l==pos) {
		tree[now].max=val;
	} else {
		if (pos<=(tree[now].l+tree[now].r)/2) 
			update(tree[now].lc,pos,val);
		if (pos>(tree[now].l+tree[now].r)/2) 
			update(tree[now].rc,pos,val);
		tree[now].max=max(tree[tree[now].lc].max,tree[tree[now].rc].max);
	}
//	cout << tree[now].l << ' ' << tree[now].r << ' ' << tree[now].max << endl;
}

int findmax(int now,int l,int r) {
	if (tree[now].l>=l&&tree[now].r<=r) {
		return tree[now].max;
	} else {
		int ans=-inf;
		if (l<=(tree[now].l+tree[now].r)/2) 
			ans=max(ans,findmax(tree[now].lc,l,r));
		if (r>(tree[now].l+tree[now].r)/2) 
			ans=max(ans,findmax(tree[now].rc,l,r));
		return ans;
	}
}

int findval(int u) {
	int x=top[u],ans=-1;
	while (x!=1) {
		ans=max(ans,findmax(1,dfn[x]-1,dfn[u]-1));
		u=fa[x];x=top[u];
	}
	ans=max(ans,findmax(1,dfn[son[x]]-1,dfn[u]-1));
	return ans;
}

int main() {
	int cas;
	scanf("%d",&cas);
	while (cas--) {
		int n,i,j,m;
		scanf("%d",&n);
		for (i=1;i<n;i++) {
			scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].d);
			addedge(a[i].x,a[i].y);
		}
		mem0(visit);
		dfs(1,0);
		mem0(visit);
		num=0;
		dfs2(1,1);
		sort(a+1,a+n,cmp);
		scanf("%d",&m);
		build(1,1,n-1);
		for (i=1;i<=m;i++) {
			scanf("%d%d",&q[i].x,&q[i].y);
			q[i].id=i;
		}
		sort(q+1,q+m+1,cmp2);
		j=1;
		for (i=1;i<=m;i++) {
			while (a[j].d<=q[i].y&&j<n) {
				update(1,max(dfn[a[j].x],dfn[a[j].y])-1,a[j].d);
				j++;
			}
			ans[q[i].id]=findval(q[i].x);
		}
		for (i=1;i<=m;i++) printf("%d\n",ans[i]);
		for (i=1;i<=n;i++) v[i].clear();
	}
	return 0;
}



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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值