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 wants to earn as much money as possible in each path. When he move along a path, he can choose one city to buy some goods and sell them in a city after it. The goods in all cities are the same but the prices are different. Now your task is to calculate the maximum possible profit on each path.

Input

The first line contains N, the number of cities.
Each of the next N lines contains wi the goods' price in each city.
Each of the next N-1 lines contains labels of two cities, describing a road between the two cities.
The next line contains Q, the number of paths.
Each of the next Q lines contains labels of two cities, describing a path. The cities are numbered from 1 to N.

1 ≤ NwiQ ≤ 50000

Output

The output contains Q lines, each contains the maximum profit of the corresponding path. If no positive profit can be earned, output 0 instead.

Sample Input

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

Sample Output

4
2
2
0
0
0
0
2
0

Source

题目大意:给一棵N个点的树,每个点上都买东西,给你每个点上的价格,现在有一个商人,当他从一个点出发走到另一个点的时候(因为是树,路径唯一),在路上有一次机会在一个点上买一个东西,而在后面的一个点上卖掉来挣钱,当然他也可以不要这一次机会。现在的问题是,给出M个询问,每个询问一个起点,一个终点,你来回答路上最多能挣多少钱。

思路:(天哪,这是我见过最恶心的lca!没有之一!!!)

我们维护4个值,一是到当前点的最大值,二是到当前点的最小值,三是从上往下(从父亲到儿子)的最大利润,四是从下往上(从儿子到父亲)的最大利润。

然后我们进行倍增更新这四个值。由于我们是一棵树,所以我们可以用当前点的儿子和他本身来更新这几个值

也就是这样:  shop[x][i].maxx=max(shop[x][i-1].maxx,shop[shop[x][i-1].dad][i-1].maxx);
        shop[x][i].minn=min(shop[x][i-1].minn,shop[shop[x][i-1].dad][i-1].minn);

有人会问不是说要用他自己和他的儿子来更新吗?!那shop[shop[x][i-1].dad][i-1].minn这又是个什么鬼?!

这个地方我也是纠结了好长时间,我们更新的时候有一句话是这样的:shop[x][i].dad=shop[shop[x][i-1].dad][i-1].dad;这样的话也就是说这两个点是相等的。为什么?!我们来看shop[x][i].dad这里是x的第2^i个父亲,后面的是它的第2^(i-1)的第2^(i-1)个父亲,我们可以代入数据试一下,这两个值是相等的。例如:当i=1的时候她的第二个父亲不就是它的父亲的父亲吗。。。当i=2的时候,2^2=(2^1)+(2^1)  当i=3时,2^3=(2^2)+(2^2)   当i=4 2^4=2^3+2^3………………这样我们就可以很好地理解为什么会是这样了吧、、、是不是又在想那直接更新不就行了,让过来绕过去不还是用它自己更新吗、、、可是我们知道我们是挨着更新的,i-1是更新过的但是i就不保证是更新过的了。。。。

然后我们再求lca,为什么要求lca?!

啊啊啊,你去一个地方肯定是走最近的路了,那不就是一定会走lca吗、、、(除非你闲的没事干、、、)

哼,有位大佬跟我说,求lca是因为他没法倒着走,如果走到比LCA深度还深的点,就到不了目的地了、、、、、、

所以我们的路径分为两种情况一个是往上走的另一个是往下走的,我们给出的数据保证第一个数是往上走,第二个数可能是lca也可能往下走。

这样我们就可以明白为什么我们要记录从上往下(从父亲到儿子)的最大利润,从下往上(从儿子到父亲)的最大利润了。

我们在进行得到结果时会有这三种买卖的情况,一是我们在x到lca这进行交易完毕,二是我们在lca到y才进行交易,三是我们在x到lca处买入在lca到y处卖出、、、所以我们对于每一组询问,更新从x到lca的最小值,更新从lca到y的最大值,然后在最后经行比较,同样我们需要更新从上到下可获得最大利润以及从下到上可获得最小利润,这个地方我们采用倍增。

代码:

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>
#define N 200010
#define maxn 9999999
using namespace std;
int n,m,x,y,tot,v[N],head[N],deep[N];
struct Edge
{
    int to,from,next;
}edge[N<<];
struct Shop
{
    int dad,minn,maxx,up_down,down_up;
}shop[N][];
int add(int x,int y)
{
    tot++;
    edge[tot].to=y;
    edge[tot].next=head[x];
    head[x]=tot;
}
int read()
{
    ,f=;char ch=getchar();
    ; ch=getchar();}
    +ch-'; ch=getchar();}
    return x*f;
}
int dfs(int x,int fa)
{
    deep[x]=deep[fa]+;
    shop[x][].maxx=max(v[x],v[fa]);
    shop[x][].minn=min(v[x],v[fa]);
    shop[x][].up_down=max(,v[x]-v[fa]);
    shop[x][].down_up=max(,v[fa]-v[x]);
    ;shop[x][i-].dad;i++)
    {
        shop[x][i].dad=shop[shop[x][i-].dad][i-].dad;
        shop[x][i].maxx=max(shop[x][i-].maxx,shop[shop[x][i-].dad][i-].maxx);
        shop[x][i].minn=min(shop[x][i-].minn,shop[shop[x][i-].dad][i-].minn);
        shop[x][i].down_up=max(shop[x][i-].down_up,shop[shop[x][i-].dad][i-].down_up);
        shop[x][i].down_up=max(shop[x][i].down_up,shop[shop[x][i-].dad][i-].maxx-shop[x][i-].minn);
        shop[x][i].up_down=max(shop[x][i-].up_down,shop[shop[x][i-].dad][i-].up_down);
        shop[x][i].up_down=max(shop[x][i].up_down,shop[x][i-].maxx-shop[shop[x][i-].dad][i-].minn);
    }
    for(int i=head[x];i;i=edge[i].next)
    {
        int t=edge[i].to;
        ].dad!=t)
         shop[t][].dad=x,dfs(t,x);
    }
}
int Lca(int x,int y)
{
    if(deep[x]>deep[y]) swap(x,y);
    ;i>=;i--)
     if(deep[shop[y][i].dad]>=deep[x])
      y=shop[y][i].dad;
    if(x==y) return x;
    ;i>=;i--)
     if(shop[x][i].dad!=shop[y][i].dad)
      x=shop[x][i].dad,y=shop[y][i].dad;
    ].dad;
}
int ask(int x,int y)
{
    ,maxx=-maxn,minn=maxn,lca=Lca(x,y);
    ;i>=;i--)
     if(deep[shop[x][i].dad]>=deep[lca])
       {
             ans=max(ans,max(shop[x][i].down_up,shop[x][i].maxx-minn));
             minn=min(shop[x][i].minn,minn);
             x=shop[x][i].dad;
      }
    ;i>=;i--)
     if(deep[shop[y][i].dad]>=deep[lca])
      {
          ans=max(ans,max(shop[y][i].up_down,maxx-shop[y][i].minn));
          maxx=max(shop[y][i].maxx,maxx);
          y=shop[y][i].dad;
      }
    return max(ans,maxx-minn);
}
int main()
{
    n=read();
    ;i<=n;i++) v[i]=read();
    ;i<n;i++) x=read(),y=read(),add(x,y),add(y,x);
    dfs(,);
    m=read();
    ;i<=m;i++)
    {
        x=read(),y=read();
        if(x==y) printf("0\n");
        printf("%d\n",ask(x,y));
    }
    ;
}

mdzz这个题居然因为一个数组然后调了一下午?!

什么嘛,倍增的时候倍增的数一定要比数组的第二维小!!!

#include<cstdio>
#include<cstring>
#include<cstdlib>
#include<iostream>
#include<algorithm>

#define N 200010
#define maxn 9999999
#define rg register
inline int min (int a, int b) { return a < b ? a : b; }
inline int max (int a, int b) { return a > b ? a : b; }
inline void swap (int &a, int &b) { int c = a; a = b, b = c; }
; char Buf[BUF], *buf = Buf;
int n,m,x,y,tot,v[N],head[N],deep[N];
], _from[N << ], _next[N << ];
struct Shop
{
    int dad,minn,maxx,up_down,down_up;
}shop[N][];
int add(int x,int y)
{
    _to[++ tot]=y;
    _next[tot]=head[x];
    head[x]=tot;
}
inline void read (int &n)
{
    ; !isdigit (*buf); ++ buf);
     + *buf - ', ++ buf);
}
int dfs(int x,int fa)
{
    rg int i;
    deep[x]=deep[fa]+;
    shop[x][].maxx=max(v[x],v[fa]);
    shop[x][].minn=min(v[x],v[fa]);
    shop[x][].up_down=max(,v[x]-v[fa]);
    shop[x][].down_up=max(,v[fa]-v[x]);
    ;shop[x][i-].dad;i++)
    {
        shop[x][i].dad=shop[shop[x][i-].dad][i-].dad;
        shop[x][i].maxx=max(shop[x][i-].maxx,shop[shop[x][i-].dad][i-].maxx);
        shop[x][i].minn=min(shop[x][i-].minn,shop[shop[x][i-].dad][i-].minn);
        shop[x][i].down_up=max(shop[x][i-].down_up,shop[shop[x][i-].dad][i-].down_up);
        shop[x][i].down_up=max(shop[x][i].down_up,shop[shop[x][i-].dad][i-].maxx-shop[x][i-].minn);
        shop[x][i].up_down=max(shop[x][i-].up_down,shop[shop[x][i-].dad][i-].up_down);
        shop[x][i].up_down=max(shop[x][i].up_down,shop[x][i-].maxx-shop[shop[x][i-].dad][i-].minn);
    }
    for(i=head[x];i;i=_next[i])
    {
        int t=_to[i];
        ].dad!=t)
         shop[t][].dad=x,dfs(t,x);
    }
}
int Lca(int x,int y)
{
    rg int i;
    if(deep[x]>deep[y]) swap(x,y);
    ;i>=;i--)
     if(deep[shop[y][i].dad]>=deep[x])
      y=shop[y][i].dad;
    if(x==y) return x;
    ;i>=;i--)
     if(shop[x][i].dad!=shop[y][i].dad)
      x=shop[x][i].dad,y=shop[y][i].dad;
    ].dad;
}
int ask(int x,int y)
{
    ,maxx=-maxn,minn=maxn,lca=Lca(x,y); rg int i;
    ;i>=;i--)
     if(deep[shop[x][i].dad]>=deep[lca])
       {
             ans=max(ans,max(shop[x][i].down_up,shop[x][i].maxx-minn));
             minn=min(shop[x][i].minn,minn);
             x=shop[x][i].dad;
      }
    ;i>=;i--)
     if(deep[shop[y][i].dad]>=deep[lca])
      {
          ans=max(ans,max(shop[y][i].up_down,maxx-shop[y][i].minn));
          maxx=max(shop[y][i].maxx,maxx);
          y=shop[y][i].dad;
      }
    return max(ans,maxx-minn);
}
int main()
{
    fread (buf, , BUF, stdin); read (n); rg int i;
    ;i<=n;i++) read (v[i]);
    ;i<n;i++) read (x), read (y),add(x,y),add(y,x);
    dfs(,), read (m);
    ;i<=m;i++)
    {
        read (x), read (y);
        if(x==y) printf("0\n");
        else printf("%d\n",ask(x,y));
    }
    ;
}

poj——3728 The merchant的更多相关文章

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

    The merchant Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 4556   Accepted: 1576 Desc ...

  2. poj 3728 The merchant(LCA)

    Description There are N cities in a country, and there is one and only one simple path between each ...

  3. POJ 3728 The merchant(并查集+DFS)

    [题目链接] http://poj.org/problem?id=3728 [题目大意] 给出一棵树,每个点上都可以交易货物,现在给出某货物在不同点的价格, 问从u到v的路程中,只允许做一次买入和一次 ...

  4. [POJ 3728]The merchant

    Description There are N cities in a country, and there is one and only one simple path between each ...

  5. POJ 3728 The merchant(LCA+DP)

    The merchant Time Limit : 6000/3000ms (Java/Other)   Memory Limit : 131072/65536K (Java/Other) Total ...

  6. poj 3728 The merchant 倍增lca求dp

    题目: zdf给出的题目翻译: 从前有一个富饶的国度,在这里人们可以进行自由的交易.这个国度形成一个n个点的无向图,每个点表示一个城市,并且有一个权值w[i],表示这个城市出售或收购这个权值的物品.又 ...

  7. POJ 3728 The merchant (树形DP+LCA)

    题目:https://vjudge.net/contest/323605#problem/E 题意:一棵n个点的树,然后有m个查询,每次查询找(u->v)路径上的两个数,a[i],a[j],(i ...

  8. POJ——T 3728 The merchant

    http://poj.org/problem?id=3728 Time Limit: 3000MS   Memory Limit: 65536K Total Submissions: 5068   A ...

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

    题意:给定一个N个节点的树,1<=N<=50000 每个节点都有一个权值,代表商品在这个节点的价格.商人从某个节点a移动到节点b,且只能购买并出售一次商品,问最多可以产生多大的利润. 思路 ...

随机推荐

  1. JS操作CSS

    <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/ ...

  2. Spring------IOC&DI

    一.Spring? Spring兴起:2003年,由Rod Johnson创建.总的来说,Spring Framwork从它诞生至今都一直为人所称道,它的伟大之处自此可见一斑. 核心:IOC& ...

  3. ES之值类型以及堆和栈

    ES的数据类型: 原始类型(值存在栈内存中): Number.String Boolean.undefined.null charAt(index)返回该index所在的字节,charCodeAt(i ...

  4. ijkplayer seekTo回跳以前从指定位置播放解决办法

    相信在使用ijkplayer播放视频时候,大部分情况会遇到SEEKTO的问题,就是拖动后,不会从拖动结束的位置播放,而是大部分拖动后,会回跳一段时间,甚至从头开始播放. 官方称这 是正常的,因为视频拖 ...

  5. Farseer.net轻量级ORM开源框架 V1.x 入门篇:存储过程数据操作

    导航 目   录:Farseer.net轻量级ORM开源框架 目录 上一篇:Farseer.net轻量级ORM开源框架 V1.x 入门篇:存储过程实体类映射 下一篇:Farseer.net轻量级ORM ...

  6. 1、QQ装机部落---腾讯软件

    亲,赚钱快人一步,我给你推荐QQ装机部落!大品牌,口碑好,知名软件,绿色无毒,每天结算,回报高!到这里注册:http://zjbl.qq.com/#/?invid=476058088 返利网邀请码立即 ...

  7. MAC加域重复跳出---"talagent"想使用“本地项目” 的钥匙串

    很简单的解决办法,就是把以前的钥匙串给删掉就好 (重要提示:这个方法,以前所有程序自动记录密码都会丢掉,safari的自动填充,QQ自动登录,imessages 的等等) 1.打开Finder -&g ...

  8. 我用的主机,推荐给大家【gegehost】【戈戈主机】

    炎炎夏日冰点价格:戈戈主机史上最大优惠促销活动 1.7月1日至8日:买主机优惠大促销:主机买一送一,不限购买数量 请您通过客户中心或者淘宝购买一个主机之后,登录客户中心,提交问题, 提供要赠送的主机的 ...

  9. 解剖嵌入式设备开发时以SD卡启动时SD卡的存储结构(以三星exynos4412为例)

    目前面对高性能产品的嵌入式开发中,用SD卡来代替以往的JLINK显得备受大家喜欢,而且MCU厂家也对以SD卡启动的支持度越来越大,反而对JLINK不在那么重视(不过依旧保留着).一些以开发开发板的公司 ...

  10. CSS 实现斑马条纹

    Part.1 linear-gradient() linear-gradient() 函数用于创建一个线性渐变的 "图像".为了创建一个线性渐变,你需要设置一个起始点和一个方向(指 ...