首页 > 代码库 > CODEVS3304 水果姐逛水果街
CODEVS3304 水果姐逛水果街
(本来想做完水果姐系列再写的,但是突然发现明天就要出发noip了,所以。。。)
题目描述 Description
水果姐今天心情不错,来到了水果街。
水果街有n家水果店,呈直线结构,编号为1~n,每家店能买水果也能卖水果,并且同一家店卖与买的价格一样。
学过oi的水果姐迅速发现了一个赚钱的方法:在某家水果店买一个水果,再到另外一家店卖出去,赚差价。
就在水果姐窃喜的时候,cgh突然出现,他为了为难水果姐,给出m个问题,每个问题要求水果姐从第x家店出发到第y家店,途中只能选一家店买一个水果,然后选一家店(可以是同一家店,但不能往回走)卖出去,求每个问题中最多可以赚多少钱。
思路:水果姐系列的线性问题,用线段树维护,节省时间。用结构体中的四项(区间最大、小值,区间最大贸易值(正、反))。这里有一个很巧妙的东西,就是对于区间[a,b],它的最大、小值比较简单,但是最大贸易值由左右孩子区间的最大贸易值和左右区间的最大最小值的差值得到,进行更新。一开始用了四个数组,后来发现tle,于是就借鉴了dada的程序,改成了结构体,结果又犯了个神奇的错误(直接将tree的值更改了),只需返回值就可以了。。。
#include<iostream>#include<cstdio>using namespace std;struct use{ int maxi,mini,zan,fan;}tr[800000];int a[200001]={0},n;void build(int i,int l,int r){ int mid; if (l==r) { tr[i].maxi=tr[i].mini=a[l]; return; } mid=(l+r)/2; build(i*2,l,mid); build(i*2+1,mid+1,r); tr[i].maxi=max(tr[i*2].maxi,tr[i*2+1].maxi); tr[i].mini=min(tr[i*2].mini,tr[i*2+1].mini); tr[i].zan=max(tr[i*2].zan,max(tr[i*2+1].zan,tr[i*2+1].maxi-tr[i*2].mini)); tr[i].fan=max(tr[i*2].fan,max(tr[i*2+1].fan,tr[i*2].maxi-tr[i*2+1].mini));}struct use work(int i,int l,int r,int x,int y){ int mid,maxn=0; struct use tem,temm,temi; if (x>r||y<l) return (use){-1,2100000000,-1,-1}; if (x<=l&&r<=y) return tr[i]; mid=(l+r)/2; tem=work(i*2,l,mid,x,y); temm=work(i*2+1,mid+1,r,x,y); temi.maxi=max(tem.maxi,temm.maxi); temi.mini=min(tem.mini,temm.mini); temi.zan=max(tem.zan,max(temm.zan,temm.maxi-tem.mini)); temi.fan=max(tem.fan,max(temm.fan,tem.maxi-temm.mini)); return temi;}int main(){ int m,i,j,x,y; struct use ans; scanf("%d",&n); for (i=1;i<=n;++i) scanf("%d",&a[i]); build(1,1,n); scanf("%d",&m); for (i=1;i<=m;++i) { scanf("%d%d",&x,&y); if (x==y) printf("0\n"); else { if (x<y) { ans=work(1,1,n,x,y); printf("%d\n",ans.zan); } else { ans=work(1,1,n,y,x); printf("%d\n",ans.fan); } } }}
CODEVS3304 水果姐逛水果街
声明:以上内容来自用户投稿及互联网公开渠道收集整理发布,本网站不拥有所有权,未作人工编辑处理,也不承担相关法律责任,若内容有误或涉及侵权可进行投诉: 投诉/举报 工作人员会在5个工作日内联系你,一经查实,本站将立刻删除涉嫌侵权内容。