• codevs 3305 水果姐逛水果街二


    在倍增LCA的基础上做一些改进。

    开四个二位数组ma,mi,premax,submax分别表示:从i到anc[i][...]的最大,最小值,从i到anc[i][...]的最大获利,从anc[i][...]到i的最大获利。

    考虑如何更新?对于ma,mi,直接依照anc的方法进行更新即可。

                        对于premax,submax,则要再考虑行走方向,依据ma,mi进行更新。转移方程见方程。
    考虑如何倍增求值?

                        令x,y的lca为z。分成从x到z,从y到z两步处理。

                         每次考虑运用ma配mi,premax或submax对ans进行更新,并记录maxx或minn值。

                        两步进行完之后,再maxx-minn与ans最后更新,即可得到正解。

    注意?数组大小!!!!!!!!附上程序。

    #include<iostream>
    #include<cstdio>
    #include<cstring>
    #include<cmath>
    #define maxv 400050
    #define maxe 400050
    #define maxq 10050
    using namespace std;
    struct edge
    {
    	long long v,nxt;
    }e[maxe];
    long long g[maxv]={0},n,m,x,y,price[maxv],nume=0;
    long long ma[maxv][22]={0},mi[maxv][22],premax[maxv][22]={0},submax[maxv][22]={0},anc[maxv][22]={0};
    long long dis[maxv]={0},ans=0;
    bool vis[maxv]={false};
    void addedge(long long u,long long v)
    {
    	e[++nume].v=v;
    	e[nume].nxt=g[u];
    	g[u]=nume;
    }
    void dfs(long long u)
    {
    	vis[u]=true;
    	for (long long i=g[u];i;i=e[i].nxt)
    	{
    		long long v=e[i].v;
    		if (vis[v]==false)
    		{
    			anc[v][0]=u;
    			ma[v][0]=max(price[v],price[u]);
    			mi[v][0]=min(price[v],price[u]);
    			premax[v][0]=price[u]-price[v];
    			submax[v][0]=price[v]-price[u];
    			dis[v]=dis[u]+1;
    			dfs(v);
    		}
    	}
    }
    long long lca(long long x,long long y)
    {
    	if (dis[x]>dis[y]) swap(x,y);
    	for (long long i=14;i>=0;i--)
    	{
    		if (dis[anc[y][i]]>=dis[x])
    			y=anc[y][i];
    	}
    	for (long long i=14;i>=0;i--)
    	{
    		if (anc[x][i]!=anc[y][i])
    		{
    			x=anc[x][i];
    			y=anc[y][i];
    		}
    	}
    	if (x==y) return x;
    	else return anc[x][0];
    }
    void jump()
    {
    	ans=0;
    	long long z=lca(x,y),minn=1234567,maxx=0;
    	long long t;
    	t=dis[x]-dis[z];
    	if (t>0)
    	{
    		for (long long i=14;i>=0;i--)
    		{
    			if (t>=(1<<i))//
    			{
    				t=t-(1<<i);
    				ans=max(premax[x][i],ans);
    				ans=max(ma[x][i]-minn,ans);
    				minn=min(minn,mi[x][i]);
    				x=anc[x][i];
    			}
    		}
    	}
    	t=dis[y]-dis[z];
    	if (t>0)
    	{
    		for (long long i=14;i>=0;i--)
    		{
    			if (t>=(1<<i))
    			{
    				t=t-(1<<i);
    				ans=max(submax[y][i],ans);
    				ans=max(ans,maxx-mi[y][i]);
    				maxx=max(maxx,ma[y][i]);
    				y=anc[y][i];
    			}
    		}
    	}
    	ans=max(ans,maxx-minn);
    } 
    int main()
    {
    	scanf("%lld",&n);
    	for (long long i=1;i<=n;i++)
    		scanf("%lld",&price[i]);
    	for (long long i=1;i<=n-1;i++)
    	{
    		scanf("%lld%lld",&x,&y);
    		addedge(x,y);
    		addedge(y,x);
    	}
    	dis[0]=-1;
    	dfs(1);
    	for (long long i=1;i<=14;i++)
    		for (long long j=1;j<=n;j++)
    		{
    			anc[j][i]=anc[anc[j][i-1]][i-1];
    			ma[j][i]=max(ma[j][i-1],ma[anc[j][i-1]][i-1]);
    			mi[j][i]=min(mi[j][i-1],mi[anc[j][i-1]][i-1]);
    			premax[j][i]=max(max(premax[j][i-1],premax[anc[j][i-1]][i-1]),ma[anc[j][i-1]][i-1]-mi[j][i-1]);
    			submax[j][i]=max(max(submax[j][i-1],submax[anc[j][i-1]][i-1]),ma[j][i-1]-mi[anc[j][i-1]][i-1]);
    		}
    	scanf("%lld",&m);
    	for (long long i=1;i<=m;i++)
    	{
    		scanf("%lld%lld",&x,&y);
    		jump();
    		printf("%lld
    ",ans);
    	}
    	return 0;
    }
  • 相关阅读:
    七牛云李意扬:如何收集 Go 实时覆盖率丨ECUG Meetup 回顾
    OpenTelemetry 微服务链路追踪
    空接口
    安全规则集合
    采用最快回应
    Golang单元测试实战
    源码 kratos 配置热加载分析
    烟花 光影
    控制Repeater显示列数
    基本代码安全知识
  • 原文地址:https://www.cnblogs.com/ziliuziliu/p/5091433.html
Copyright © 2020-2023  润新知