CODEVS 3304 水果姐逛水果街Ⅰ

题目描述 

水果姐今天心情不错,来到了水果街。

水果街有n家水果店,呈直线结构,编号为1~n,每家店能买水果也能卖水果,并且同一家店卖与买的价格一样。

学过oi的水果姐迅速发现了一个赚钱的方法:在某家水果店买一个水果,再到另外一家店卖出去,赚差价。

就在水果姐窃喜的时候,cgh突然出现,他为了为难水果姐,给出m个问题,每个问题要求水果姐从第x家店出发到第y家店,途中只能选一家店买一个水果,然后选一家店(可以是同一家店,但不能往回走)卖出去,求每个问题中最多可以赚多少钱。

输入描述

第一行n,表示有n家店

下来n个正整数,表示每家店一个苹果的价格。

下来一个整数m,表示下来有m个询问。

下来有m行,每行两个整数xy,表示从第x家店出发到第y家店。

输出描述

m行。

每行对应一个询问,一个整数,表示面对cgh的每次询问,水果姐最多可以赚到多少钱。

样例输入 

10
2 8 15 1 10 5 19 19 3 5
 
4
6 6
2 8
2 2
6 3

样例输出 

0
18
0
14

数据范围及提示 

0<=苹果的价格<=10^8

0<n,m<=200000

题解:线段树保存最大值、最小值、从左到右的最大差价、从右到左的最大差价。将两棵子树合并成一棵子树是这道题目的关键。通过使用update算出父节点的各个值,父节点的最大值即是子节点中的最大值,最小值即是子节点中的最小值,从左到右的最大差价即是左子树本来的从左到右的最大差价,右子树本来的从左到右的最大差价,右子树的最大值减去左子树的最小值这三者之间的最大值,从右到左的最大差价即是左子树本来的从右到左的最大差价,右子树本来的从右到左的最大差价,左子树的最大值减去右子树的最小值这三者之间的最大值,是op用来记录是要查询的是从左往右走,还是从右往左走,最后算出答案即可。

#include <cstdio>
#include <algorithm>
int n,m,x,y,op;
int a[200005];
struct tree{
	int l,r,mx,mn,ls,rs;
}t[800005];
tree ans;
const int INF=1e9;
using namespace std;
inline int read()            
{  
    int f=1,x=0;            
    char ch=getchar();            
    if (ch=='-')            
    {            
        f=-1;            
        ch=getchar();            
    }            
    while ((ch<'0')||(ch>'9')) ch=getchar();            
    while ((ch>='0')&&(ch<='9'))            
    {            
        x=x*10+ch-48;            
        ch=getchar();            
    }            
    return f*x;            
}
tree update(tree x,tree y)
{
	tree ans;
	ans.l=x.l;
	ans.r=y.r;
	ans.mx=max(x.mx,y.mx);
	ans.mn=min(x.mn,y.mn);
	ans.ls=max(max(x.ls,y.ls),y.mx-x.mn);
	ans.rs=max(max(x.rs,y.rs),x.mx-y.mn);
	return ans;
}
inline void build(int root,int l,int r)
{
	t[root].l=l,t[root].r=r;
	if (l==r) 
	{
		t[root].mx=t[root].mn=a[l];
		return;
	}
	build(root<<1,l,(l+r)/2);
	build(root<<1|1,(l+r)/2+1,r);
	t[root]=update(t[root*2],t[root*2+1]);
}
inline void find(int root,int l,int r)
{
	int ll=t[root].l,rr=t[root].r;
	int mid=(ll+rr)/2;
	if ((l<=ll)&&(rr<=r))
	{
		ans=update(ans,t[root]);
		return;
	}
	if (l<=mid) find(root*2,l,r);
	if (r>mid) find(root*2+1,l,r);
}
int main()
{
	//freopen("1.in","r",stdin);
	n=read();
	for (int i=1;i<=n;i++) a[i]=read();
	build(1,1,n);
	m=read();
	for (int i=1;i<=m;i++)
	{
		x=read(),y=read();
		op=0;
		if (x==y)
		{
			printf("0\n");
            continue;
		}
		if (x>y)
		{
			swap(x,y);
            op=1;
		}
		ans.mn=INF;
		ans.mx=-INF;
		ans.ls=ans.rs=0;
		find(1,x,y);
        if (op) printf("%d\n",ans.rs);
            else printf("%d\n",ans.ls);
	}
	return 0;
}

猜你喜欢

转载自blog.csdn.net/zhouhongkai06/article/details/80372154