zoukankan      html  css  js  c++  java
  • 越野赛车问题

    题目描述
    小 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
    ",ans[read()]);
    	return 0;
    }
    
  • 相关阅读:
    Delphi Variant 通用类型[3] 流 Stream的相互转换
    Delphi System单元 Utf8ToAnsi、AnsiToUtf8、Utf8Decode、Utf8Encode、Utf8ToUnicode、UnicodeToUtf8 转换
    OCR (Optical Character Recognition,光学字符识别)
    使用Python写Windows Service服务程序
    双精度张量内核加快了高性能计算
    A100计算能力
    A100 Tensor核心可加速HPC
    A100 GPU硬件架构
    NVIDIA深度架构
    稀疏性如何为AI推理增加难度
  • 原文地址:https://www.cnblogs.com/nofind/p/13041828.html
Copyright © 2011-2022 走看看