POJ 3728

题意:

  一个树形图,有个二货商人,旅游时候还想着赚钱!从某个地方到另一个地方时,可以旅途中进一批货(应该人手不够,手里只能拿一批),然后在旅途中卖掉,求最大能赚多少钱。

思路:

  赤裸裸的LCA,ans(x,y)=max(up(x,lca),down(lca,y),maxp(lca,y)-min(lca,x));

  注意每次更新要在父亲节点处更新,繁琐了些。还是多用用STL吧!

  竟然犯了一个无语的RE,忘了是双向边。去切腹吧  — 。—

代码:

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <cstdlib>
#include <cmath>
#include <utility>
#include <vector>
#include <queue>
#include <map>
#include <set>
#define max(x,y) ((x)>(y)?(x):(y))
#define min(x,y) ((x)>(y)?(y):(x))

using namespace std;

long long maxp[50005],minp[50005],up[50005],down[50005];
int be[50005],all;
int bq[50005],qall;
long long question[50005][3];
int f[50005];
bool vis[50005];
int x,y,n,q;

struct Edge{
    int y,ne;
}e[150005];
struct Query{
    int y,res,ne;
}query[150005];
vector<int> num[50005];

void add(int x, int y)
{
    e[all].y=y;
    e[all].ne=be[x];
    be[x]=all++;

    e[all].y=x;
    e[all].ne=be[y];
    be[y]=all++;
}
void qadd(int x, int y, int i)
{
    query[qall].y=y;
    query[qall].res=i;
    query[qall].ne=bq[x];
    bq[x]=qall++;

    query[qall].y=x;
    query[qall].res=i;
    query[qall].ne=bq[y];
    bq[y]=qall++;
}

int find(int x)
{
    int oldf=f[x];
    if(f[x]!=x) f[x]=find(f[x]);
    up[x]=max(max(up[x],up[oldf]),maxp[oldf]-minp[x]);
    down[x]=max(max(down[x],down[oldf]),maxp[x]-minp[oldf]);
    maxp[x]=max(maxp[oldf],maxp[x]);
    minp[x]=min(minp[oldf],minp[x]);
    return f[x];
}

void tarjan(int u)
{
    vis[u]=1;
    for(int i=be[u]; i!=-1; i=e[i].ne)
    {
        int v=e[i].y;
        if(!vis[v])
        {
            tarjan(v);
            f[v]=u;
        }
    }

    for(int i=bq[u]; i!=-1; i=query[i].ne)
        if(vis[query[i].y])
        {
            int fx=find(query[i].y);
            num[fx].push_back(query[i].res);
        }

    for(vector<int>::iterator it=num[u].begin(); it!=num[u].end(); it++)
    {
        int x=question[*it][0], y=question[*it][1];
        find(x);
        find(y);
        question[*it][2]=max(max(up[x],down[y]),maxp[y]-minp[x]);
    }
}

int main()
{
    scanf("%d",&n);
    for(int i=1; i<=n; i++)
    {
        scanf("%d",&x);
        minp[i]=maxp[i]=x;
        up[i]=down[i]=0;
        f[i]=i;
    }
    memset(be,-1,sizeof(be));
    memset(bq,-1,sizeof(bq));
    all=qall=0;
    memset(vis,0,sizeof(vis));

    for(int i=1; i<=n-1; i++)
    {
        scanf("%d%d",&x,&y);
        add(x,y);
    }

    scanf("%d",&q);
    for(int i=1; i<=q; i++)
    {
        scanf("%d%d",&x,&y);
        qadd(x,y,i);
        question[i][0]=x;
        question[i][1]=y;
        question[i][2]=0;
    }

    tarjan(1);

    for(int i=1; i<=q; i++)
        printf("%d\n",question[i][2]);

    return 0;
}

还能用RMQ做,待我取经回来再搞一发!

时间: 2024-08-01 10:27:36

POJ 3728的相关文章

[最近公共祖先] POJ 3728 The merchant

The merchant Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 4556   Accepted: 1576 Description There are N cities in a country, and there is one and only one simple path between each pair of cities. A merchant has chosen some paths and w

poj——3728 The merchant

The merchant Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 5055   Accepted: 1740 Description There are N cities in a country, and there is one and only one simple path between each pair of cities. A merchant has chosen some paths and w

poj 3728 The merchant(LCA)

Description There are N cities in a country, and there is one and only one simple path between each pair of cities. A merchant has chosen some paths and wants to earn as much money as possible in each path. When he move along a path, he can choose on

POJ - 3728 The merchant(dp+LCA)

题目大意:给出N个点,和每个点物品的售价,现在有一个商人,要从u点到v点,他想在路上多赚点钱.他可以从一个城市买物品,然后再卖到另一个城市,但买卖只允许一次,且不能回头走 问最多能赚多少 解题思路:果然智商捉急了.. up数组纪录当前点到lca的最大利润 down数组纪录lca到当前点的最大利润 Max数组lca到当前点的最大值 Min纪录当前点到lca的最小值 这样的话,执行tarjan的时候,就可以更新一下这些值了 首先,答案的话肯定是max(max(up, down), Max - Min

POJ 3728 离线 LCA

题意很简单 给一个树(n < 5w) 每个点有个权值,代表商品价格 若干个询问(5w) 对每个询问,问的是从u点走到v点(简单路径),商人在这个路径中的某点买入商品,然后在某点再卖出商品,   最大可能是多少 注意一条路径上只能买卖一次,先买才能卖 用的方法是离线LCA,在上面加了一些东西 对于一个询问, 假设u,v的LCA是f 那么有三种可能, 一个是从u到f 买卖了. 一个是从f到v买卖了,  一个是从u到f之间买了,从v到f卖了 从u到f 我们称为up,  从f到v我们称为down,而从u

POJ 3728 Catch That Cow

Description Farmer John has been informed of the location of a fugitive cow and wants to catch her immediately. He starts at a point N (0 ≤ N ≤ 100,000) on a number line and the cow is at a point K (0 ≤ K ≤ 100,000) on the same number line. Farmer Jo

POJ - 3728:The merchant (Tarjan 带权并查集)

题意:给定一个N个节点的树,1<=N<=50000 每个节点都有一个权值,代表商品在这个节点的价格.商人从某个节点a移动到节点b,且只能购买并出售一次商品,问最多可以产生多大的利润. 思路:路径压缩,得到每个点到当前根的信息,然后更新即可. 有可以用倍增做. 很久前抄的代码. #include<cstdio> #define min(a,b) (a<b?a:b) #define max(a,b) (a>b?a:b) #define swap(a,b) (a^=b,b^=

学习 LCA&amp;&amp;RMQ

参考:点击打开链接 点击打开链接      点击打开链接(一些总结) 点击打开链接(不错的模板) 题目:点击打开链接 花了4天时间做完了这个专题,LCA的问题用处还是很大,同时能体会RMQ的ST算法中dp的味道.基本方法就是ST,LCA转RMQ,LCA的Tarjan,LCA倍增(这个可存储边权) 这个专题后面四道题都非常好,推荐大家做做. 细节: 1. ST方法2^i 包含自己,因此其真实只包含到i+2^k-1的范围. 2. Tarjan一般都很快,但不适合修改类型的问题,关于权值长度之类的,S

LCA&amp;&amp;RMQ问题

参考:点击打开链接 点击打开链接      点击打开链接(一些总结) 点击打开链接(不错的模板) 题目:点击打开链接 花了4天时间做完了这个专题,LCA的问题用处还是很大,同时能体会RMQ的ST算法中dp的味道.基本方法就是ST,LCA转RMQ,LCA的Tarjan,LCA倍增(这个可存储边权) 这个专题后面四道题都非常好,推荐大家做做. 细节: 1. ST方法2^i 包含自己,因此其真实只包含到i+2^k-1的范围. 2. Tarjan一般都很快,但不适合修改类型的问题,关于权值长度之类的,S