HDU - 3804 Query on a tree 树链剖分+线段树+离线 或 主席树 或 multiset

题目链接:点击查看

题意:给出一个树和边权,求节点到根节点路径上的比y小的最大的

题解:本来写了个主席树,超内存了,然后改写树链剖分+线段树,但这样需要离线处理,从小到大来进行,然后就过了,看了之前的代码,感觉主席树不会超内存啊,果断把vector换掉了,就不超了,真是垃圾,以后不会再用vector记录图了,不超时就T了,之前我是二分的答案,然后就T了,细想发现没必要,我们把主席树保存的val值,都记录成该区间内,存在数的最右端的位置,这样只扫一遍就可以了,晚上脑子真是不好用.....

第二天突然想到,既然查询的店都是到节点1的路径上的,那么我们dfs一次就行了,离线操作一下,到哪个点处理哪个,注意要用multiset,删除的时候要按位置删除一个。

树链剖分:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
int n,q;
vector<pair<int,int> >v[N];
struct node{
	int l,r;
	int val;
}tree[N<<2];
struct node1{
	int x,y,z;
	bool operator<(const node1 &xx)const
	{
		return z<xx.z;
	}
}e[N];
int len;
struct node2{
	int x,y;
	int id;
	bool operator<(const node2 &xx)const
	{
		return y<xx.y;
	}
}a[N];
int son[N],s_num[N];
void build(int l,int r,int cur)
{
	tree[cur].l=l;
	tree[cur].r=r;
	tree[cur].val=0;
	if(l==r)return;
	int mid=(r+l)>>1;
	build(l,mid,cur<<1);
	build(mid+1,r,cur<<1|1);
}
void dfs1(int u,int fa)
{
	s_num[u]=1;
	int to;
	int maxx=-1;
	for(int i=0;i<v[u].size();i++)
	{
		to=v[u][i].first;if(to==fa) continue;
		dfs1(to,u);
		e[++len].x=u;e[len].y=to;e[len].z=v[u][i].second;
		s_num[u]+=s_num[to];
		if(s_num[to]>maxx)
		{
			son[u]=to;
			maxx=s_num[to];
		}
	}
}
int in[N],cnt,f[N],dep[N],faa[N];
void dfs2(int u,int fa,int rt,int deep)
{
	in[u]=++cnt;
	f[u]=rt;
	dep[u]=deep;
	faa[u]=fa;
	if(son[u]!=-1)
	{
		dfs2(son[u],u,rt,deep+1);
	}
	int to;
	for(int i=0;i<v[u].size();i++)
	{
		to=v[u][i].first;if(to==fa || to==son[u]) continue;
		dfs2(to,u,to,deep+1);
	}
}
void pushup(int cur)
{
	tree[cur].val=max(tree[cur<<1].val,tree[cur<<1|1].val);
}
void update(int pos,int cur,int val)
{
	if(tree[cur].l==tree[cur].r)
	{
		tree[cur].val=val;
		return;
	}
	if(pos<=tree[cur<<1].r) update(pos,cur<<1,val);
	else update(pos,cur<<1|1,val);
	pushup(cur);
}
int query(int pl,int pr,int cur)
{
	if(pl<=tree[cur].l&&tree[cur].r<=pr)
	{
		return tree[cur].val;
	}
	int res=0;
	if(pl<=tree[cur<<1].r) res=max(res,query(pl,pr,cur<<1));
	if(pr>=tree[cur<<1|1].l) res=max(res,query(pl,pr,cur<<1|1));
	return res;
}
int ans[N];
int solve(int x,int y)
{
	int f1=f[x],f2=f[y];
	int maxx=0;
	while(f1!=f2)
	{
		if(dep[f1]<dep[f2])
		{
			swap(f1,f2);
			swap(x,y);
		}
		maxx=max(maxx,query(in[f1],in[x],1));
		x=faa[x];
		f1=f[x];
	}
	if(dep[x]>dep[y]) swap(x,y);
	if(x!=y) maxx=max(maxx,query(in[x]+1,in[y],1));
	return maxx;
}
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		cnt=len=0;
		for(int i=1;i<=n;i++) v[i].clear(),son[i]=-1;
		build(1,n,1);
		int x,y,z;
		for(int i=1;i<n;i++)
		{
			scanf("%d%d%d",&x,&y,&z);
			v[x].push_back(make_pair(y,z));
			v[y].push_back(make_pair(x,z));
		}
		dfs1(1,0);
		dfs2(1,0,1,1);
		scanf("%d",&q);
		
		for(int i=1;i<=q;i++) scanf("%d%d",&a[i].x,&a[i].y),a[i].id=i;
		sort(e+1,e+n);
		sort(a+1,a+1+q);
		for(int i=1,j=1;i<=q;i++)
		{
	//		cout<<a[i].y<<" ";
			while(j<n&&e[j].z<=a[i].y)
			{
		//		cout<<e[j].z<<" ";
				update(in[e[j].y],1,e[j].z);
				j++;
			}
		//	cout<<j<<endl;
			ans[a[i].id]=solve(1,a[i].x);
		}
		for(int i=1;i<=q;i++)
		{
			if(ans[i]==0) ans[i]=-1;
			printf("%d\n",ans[i]);
		}
	}
	return 0;
}

主席树:

#include<bits/stdc++.h>
using namespace std;
const int N=1e5+10;
struct edge{
	int to,nex,d;
}e[N*2];
int head[N],tot;
void addedge(int x,int y,int z)
{
	e[tot].to=y;
	e[tot].d=z;
	e[tot].nex=head[x];
	head[x]=tot++;
}
struct node{
	int l,r;
	int val;
}tree[N*22];
int a[N];
int root[N],cnt;
int len;
int update(int pre,int l,int r,int val)
{
	int cur=++cnt;
	tree[cur]=tree[pre];
	tree[cur].val=max(val,tree[cur].val);
	if(l==r) return cur;
	int mid=(r+l)>>1;
	if(val<=mid) tree[cur].l=update(tree[pre].l,l,mid,val);
	else tree[cur].r=update(tree[pre].r,mid+1,r,val);
	return cur;
}
void dfs(int u,int fa)
{
	int pos,to,val;
	
	for(int i=head[u];i!=-1;i=e[i].nex)
	{
		to=e[i].to;
		if(to==fa)continue;
		val=e[i].d;
		pos=lower_bound(a+1,a+1+len,val)-a;

		root[to]=update(root[u],1,len,pos);
		dfs(to,u);
	}
}
int query(int pl,int pr,int l,int r,int x)
{
	if(pl<=l&&r<=pr)
	{
//		cout<<l<<" "<<r<<" "<<tree[x].val<<endl;
		return tree[x].val;
	}
	int mid=(r+l)>>1;
	int res=0;
	if(pl<=mid) res=max(res,query(pl,pr,l,mid,tree[x].l));
	if(pr>mid) res=max(res,query(pl,pr,mid+1,r,tree[x].r));
	return res;
}
int n,q;
struct node1{
	int x,y;
}b[N];
int main()
{
	int T;
	scanf("%d",&T);
	while(T--)
	{
		cnt=0;
		scanf("%d",&n);
		for(int i=1;i<=n;i++)head[i]=-1;
		tot=0;
		int x,y,z;
		for(int i=1;i<n;i++)
		{
			scanf("%d%d%d",&x,&y,&z);
			a[i]=z;
			addedge(x,y,z);
			addedge(y,x,z);
		}
		sort(a+1,a+n);
		len=unique(a+1,a+n)-(a+1);
	//	cout<<len<<endl;
		dfs(1,0);
		int pos;
		scanf("%d",&q);
		for(int i=1;i<=q;i++)
		{
			scanf("%d%d",&x,&y);
			pos=lower_bound(a+1,a+1+len,y)-a;
			if(pos>len||a[pos]!=y) pos--;

			if(pos==0) printf("-1\n");
			else
			{
				int ans=query(1,pos,1,len,root[x]);
				if(ans==0) printf("-1\n");
				else
				printf("%d\n",a[ans]);
			}
		}
	}
	return 0;
}
/*
2
3
1 2 7
2 3 5
4
3 10
3 7
3 6
3 4
7
1 2 1
1 3 2
2 4 3
2 5 4
3 6 5
3 7 6
10
*/

multiset:

#include<bits/stdc++.h>
using namespace std;
#define mk make_pair
#define pb push_back
const int N=1e5+10;
struct edge{
	int to,nex,val;
}e[N*2];
int n,q;
int head[N],len;
vector<pair<int,int> > v[N];
multiset<int> s;
multiset<int>::iterator it;
int ans[N];
void init()
{
	len=0;
	for(int i=1;i<=n;i++)
	{
		head[i]=-1;
		v[i].clear();
	}
}
void addedge(int x,int y,int z)
{
	e[len].to=y;
	e[len].val=z;
	e[len].nex=head[x];
	head[x]=len++;
}
void dfs(int u,int fa)
{
	int to,val;
	int cnt=v[u].size(),id;
	for(int i=0;i<cnt;i++)
	{
		val=v[u][i].first;
		id=v[u][i].second;
		it=s.upper_bound(val);
		if(it==s.begin())ans[id]=-1;
		else
        {
            it--;
            ans[id]=*it;
        }
	}
	for(int i=head[u];~i;i=e[i].nex)
	{
		to=e[i].to;if(to==fa)continue;
		val=e[i].val;
		s.insert(val);
		dfs(to,u);
		it=s.lower_bound(val);
		s.erase(it);
	}

}
int main()
{
	int T;
	int x,y,z;
	scanf("%d",&T);
	while(T--)
	{
		scanf("%d",&n);
		init();
		for(int i=1;i<n;i++)
		{
			scanf("%d%d%d",&x,&y,&z);
			addedge(x,y,z);
			addedge(y,x,z);
		}
		scanf("%d",&q);
		for(int i=1;i<=q;i++)
		{
			scanf("%d%d",&x,&y);
			v[x].pb(mk(y,i));
		}
		dfs(1,0);
		for(int i=1;i<=q;i++)printf("%d\n",ans[i]);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/mmk27_word/article/details/89304914