列表

详情


NC15427. wyh的商机

描述

一天,你们wyh学长和你们zhl学长玩一个游戏,这个游戏规则是这样的

给你n个城市,保证这n个城市之间都只有一条道路可以到达。

有一件物品,在所有城市中都是一样的,但是由于各个城市的经济发展不同,导致每个城市对于这件物品销售的价格不同。

游戏一共进行Q轮。

每轮给你2个点s和t,其中s代表起点,t代表终点。

对于每一个城市都可以选择买这个物品,如果手里有这个物品的话,也可以选择卖掉这个物品,对于同一个城市来说,买和卖的价格是一样的,每一个城市只能买一件物品

现在,你们wyh学长和zhl学长都需要找到一个方案,使得从起点走到终点的时候盈利最多,请你帮助帮助他们吧

输入描述

每个测试文件中都只有一组测试数据

输入第一行一个整数n(1<=n<=50000),代表有n个城市

第二行输入n个数,代表每个城市对于这件物品的价格wi(1<=wi<=50000)

接下来有n-1行,每行2个数a和b,代表a到b之间有一条路

接下来输入一个数Q(1<=Q<=50000)

接下来Q行,每行2个数s和t


输出描述

对于每组测试数据,输出对应答案,如果从起点到终点不能盈利的话,输出0

示例1

输入:

4
1 
5 
3 
2
1 3
3 2
3 4
9
1 2
1 3
1 4
2 3
2 1
2 4
3 1
3 2
3 4

输出:

4
2
2
0
0
0
0
2
0

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++14(g++5.4) 解法, 执行用时: 155ms, 内存消耗: 14232K, 提交时间: 2020-02-21 16:04:30

#include<cstdio>
#include<vector>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=5e4+88;
vector<int>G[N],Q[N],dir[N],st[N],ed[N],pos[N];
int m,F[N],ans[N],mx[N],mi[N],up[N],down[N],n,W[N];
bool vis[N];
int find(int x){
    if(F[x]==x) return x;
    int t=find(F[x]);
    
    up[x]=max(max(up[x],up[F[x]]),mx[F[x]]-mi[x]);
    down[x]=max(max(down[x],down[F[x]]),mx[x]-mi[F[x]]);
    mi[x]=min(mi[F[x]],mi[x]);
    mx[x]=max(mx[F[x]],mx[x]);
    
    return F[x]=t;
}
void dfs(int u){
    vis[u]=1;
    for(int i=0;i<(int)Q[u].size();++i) {
        int v=Q[u][i];
        if(vis[v]) {
            int t=find(v),z=dir[u][i];
            if(z>0) {
                st[t].push_back(u);
                ed[t].push_back(v);
                pos[t].push_back(z);
            }
            else {
                st[t].push_back(v);
                ed[t].push_back(u);
                pos[t].push_back(-z);
            }
        }
    }
    for(int i=0;i<(int)G[u].size();++i) if(!vis[G[u][i]])
    dfs(G[u][i]),F[G[u][i]]=u;
    for(int i=0;i<(int)st[u].size();++i) {
        int x=st[u][i],y=ed[u][i],z=pos[u][i];
        find(x);find(y);
        ans[z]=max(mx[y]-mi[x],max(up[x],down[y]));
    }
}
int main(){
    int x,y;
    scanf("%d",&n);
    for(int i=1;i<=n;++i) scanf("%d",W+i);
    for(int i=1;i<=n;++i) F[i]=i,mx[i]=mi[i]=W[i];
    for(int i=1;i<n;++i) {
        scanf("%d%d",&x,&y);
        G[x].push_back(y);
        G[y].push_back(x);
    }
    scanf("%d",&m);
    for(int i=1;i<=m;++i) {
        scanf("%d%d",&x,&y);
        Q[x].push_back(y);
        dir[x].push_back(i);
        Q[y].push_back(x);
        dir[y].push_back(-i);
    }
    dfs(1);
    for(int i=1;i<=m;++i) printf("%d\n",ans[i]);
}

C++ 解法, 执行用时: 70ms, 内存消耗: 14128K, 提交时间: 2021-07-28 19:36:45

#include <iostream>
#include <cstdio>
#include <vector>
using namespace std;
const int N=1e5+7;
int n,m,mn[N],mx[N],up[N],down[N],ans[N],fa[N];
int vis[N];
struct node{
	int s,t,id;
};
vector<node> g[N],q[N],e[N];
int Find(int x){
	if(fa[x]==x) return x;
	int root=Find(fa[x]);
	up[x]=max(max(up[x],up[fa[x]]),mx[fa[x]]-mn[x]);
	down[x]=max(max(down[x],down[fa[x]]),mx[x]-mn[fa[x]]);
	mn[x]=min(mn[x],mn[fa[x]]);
	mx[x]=max(mx[x],mx[fa[x]]);
	return fa[x]=root;
}
void dfs(int u){
	vis[u]=1;
	for(int i=0;i<g[u].size();i++){
		node v=g[u][i];
		if(!vis[v.s]){
			dfs(v.s);
			fa[v.s]=u;
		}
	}
	for(int i=0;i<q[u].size();i++){
		node v=q[u][i];
		if(vis[v.s]){
			int lca=Find(v.s);
			if(v.id>0) e[lca].push_back({u,v.s,v.id});
			else e[lca].push_back({v.s,u,-v.id});
		}
	}
	for(int i=0;i<e[u].size();i++){
		node v=e[u][i];
		int x=v.s,y=v.t,id=v.id;
		Find(x);
		Find(y);
		ans[id]=max(mx[y]-mn[x],max(up[x],down[y]));
	}
}
int main(){
	scanf("%d",&n);
	for(int i=1;i<=n;i++){
		int w;
		scanf("%d",&w);
		mn[i]=mx[i]=w;
		fa[i]=i;
	}
	int a,b;
	node v;
	for(int i=1;i<n;i++){
		scanf("%d%d",&a,&b);
		v.s=b;
		g[a].push_back(v);
		v.s=a;
		g[b].push_back(v);
	}
	scanf("%d",&m);
	for(int i=1;i<=m;i++){
		int s,t;
		scanf("%d%d",&s,&t);
		v.s=t;
		v.id=i;
		q[s].push_back(v);
		v.s=s;
		v.id=-i;
		q[t].push_back(v);
	}
	dfs(1);
	for(int i=1;i<=m;i++) printf("%d\n",ans[i]);
	return 0;
}

上一题