码迷,mamicode.com
首页 > 其他好文 > 详细

越野赛车问题

时间:2020-06-04 10:46:34      阅读:100      评论:0      收藏:0      [点我收藏+]

标签:文件中   fine   文件   fir   space   code   owa   树分治   分治   

题目描述
小 H 是一位优秀的越野赛车女选手。现在她准备在 A 山上进行赛车训练。
A 山上一共有 n 个广场,编号依次为 1 到 n,这些广场之间通过 n?1 条双向车道直接或间接地连接在一起。对于每条车道 i,可以用四个正整数 ui,vi,li,ri 描述,表示车道连接广场 ui 和 vi,其速度承受区间为 [li,ri],即汽车必须以不小于 li 且不大于 ri 的速度经过车道 i。
小 H 计划进行 m 次训练,每次她需要选择 A 山上的一条简单路径,然后在这条路径上行驶。但小 H 不喜欢改变速度,所以每次训练时的车速都是固定的。现在小 H 告诉你她在 m 次训练中计划使用的车速,请帮助她对于每次训练,找到一条合法的路径(车速在所有车道的速度承受区间的交集内),使得路径上经过的车道数最大。
输入格式
输入文件的第一行包含两个正整数 n,m,表示广场数和训练次数。接下来 n?1 行,每行四个正整数 ui,vi,li,ri(≤n),描述所有车道。最后 m 行,每行一个正整数 v(≤n),表示小 H 每次训练时使用的车速。
输出格式
输出 m 行,将每次训练时的行驶路径经过的最大车道数输出到文件中。
输入输出样例
输入 #1
5 3
3 2 2 4
1 5 2 5
4 5 2 2
1 2 3 5
1
2
3
输出 #1
0
2
3
数据点 n m 约定
1 =5 =5
2 =20 =20
3 =50000 =50000 li=1,ui=i,vi=i+1
4 =70000 =70000 li=1,ui=i,vi=i+1
5 =50000 =50000 ui=i,vi=i+1
6 =70000 =70000 ui=i,vi=i+1
7 =50000 =50000 li=1
8 =70000 =70000 li=1
9 =50000 =50000
10 =70000 =70000

按长度线段树分治,可撤销并查集维护连通块内直径。

code:

#include<bits/stdc++.h>
using namespace std;
#define ls(p) (p<<1)
#define rs(p) (p<<1|1)
const int maxn=70010;
int n,m;
int ans[maxn];
struct Edge{int u,v,l,r;}E[maxn];
inline int read()
{
    char c=getchar();int res=0,f=1;
    while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
    while(c>=‘0‘&&c<=‘9‘)res=res*10+c-‘0‘,c=getchar();
    return res*f;
}
int cnt_edge,tim;
int head[maxn],dep[maxn],pos[maxn],lg[maxn*2];
int f[maxn*2][20];
struct edge{int to,nxt;}e[maxn<<1];
inline void add_edge(int u,int v)
{
	e[++cnt_edge]=(edge){v,head[u]};
	head[u]=cnt_edge;
}
void dfs(int x,int fa)
{
	dep[x]=dep[fa]+1;
	f[++tim][0]=x,pos[x]=tim;
	for(int i=head[x];i;i=e[i].nxt)
	{
		int y=e[i].to;
		if(y==fa)continue;
		dfs(y,x);
		f[++tim][0]=x;
	}
}
inline int lca(int x,int y)
{
	if(pos[x]>pos[y])swap(x,y);
	x=pos[x],y=pos[y];
	int t=lg[y-x+1];
	return dep[f[x][t]]<dep[f[y-(1<<t)+1][t]]?f[x][t]:f[y-(1<<t)+1][t];
}
inline int dis(int x,int y){return dep[x]+dep[y]-2*dep[lca(x,y)];}
vector<int>seg[maxn<<2];
void insert(int p,int l,int r,int ql,int qr,int id)
{
	if(l>=ql&&r<=qr){seg[p].push_back(id);return;}
	int mid=(l+r)>>1;
	if(ql<=mid)insert(ls(p),l,mid,ql,qr,id);
	if(qr>mid)insert(rs(p),mid+1,r,ql,qr,id);
}
#define pii pair<int,int>
#define mkp make_pair
#define sec second
#define fir first
int top;
int fa[maxn],size[maxn];
pii pt[maxn];
struct node
{
	int x,y;
	pii pt;
}sta[maxn<<2];
int find(int x){return fa[x]==x?x:find(fa[x]);}
inline void del(node a)
{
	int x=a.x,y=a.y;pii p=a.pt;
	fa[y]=y,size[x]-=size[y];
	pt[x]=p;
}
void solve(int p,int l,int r,int nowans)
{
	int tmp=top;
	for(unsigned int i=0;i<seg[p].size();i++)
	{
		int id=seg[p][i];
		int x=find(E[id].u),y=find(E[id].v);
		if(size[x]<size[y])swap(x,y);
		sta[++top]=(node){x,y,pt[x]};
		int maxx=dis(pt[x].fir,pt[x].sec);pii now=pt[x];
		if(dis(pt[y].fir,pt[y].sec)>maxx)maxx=dis(pt[y].fir,pt[y].sec),now=pt[y];
		if(dis(pt[x].fir,pt[y].fir)>maxx)maxx=dis(pt[x].fir,pt[y].fir),now=mkp(pt[x].fir,pt[y].fir);
		if(dis(pt[x].fir,pt[y].sec)>maxx)maxx=dis(pt[x].fir,pt[y].sec),now=mkp(pt[x].fir,pt[y].sec);
		if(dis(pt[x].sec,pt[y].fir)>maxx)maxx=dis(pt[x].sec,pt[y].fir),now=mkp(pt[x].sec,pt[y].fir);
		if(dis(pt[x].sec,pt[y].sec)>maxx)maxx=dis(pt[x].sec,pt[y].sec),now=mkp(pt[x].sec,pt[y].sec);
		pt[x]=now;fa[y]=x,size[x]+=size[y];
		nowans=max(nowans,maxx);
	}
	if(l==r)ans[l]=nowans;
	else
	{
		int mid=(l+r)>>1;
		solve(ls(p),l,mid,nowans);solve(rs(p),mid+1,r,nowans);
	}
	while(top>tmp)del(sta[top]),top--;
}
int main()
{
	n=read(),m=read();
	for(int i=1;i<n;i++)E[i].u=read(),E[i].v=read(),E[i].l=read(),E[i].r=read();
	for(int i=1;i<n;i++)add_edge(E[i].u,E[i].v),add_edge(E[i].v,E[i].u);
	dfs(1,0);
	lg[0]=-1;
	for(int i=1;i<=tim;i++)lg[i]=lg[i>>1]+1;
	for(int j=1;j<=18;j++)
		for(int i=1;i+(1<<j)-1<=tim;i++)
			f[i][j]=dep[f[i][j-1]]<dep[f[i+(1<<j-1)][j-1]]?f[i][j-1]:f[i+(1<<j-1)][j-1];
	for(int i=1;i<n;i++)insert(1,1,n,E[i].l,E[i].r,i);
	for(int i=1;i<=n;i++)fa[i]=i,size[i]=1,pt[i]=mkp(i,i);
	solve(1,1,n,0);
	while(m--)printf("%d\n",ans[read()]);
	return 0;
}

越野赛车问题

标签:文件中   fine   文件   fir   space   code   owa   树分治   分治   

原文地址:https://www.cnblogs.com/nofind/p/13041828.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!