最优贸易简化版
来源:互联网 发布:有多少网络交易平台 编辑:程序博客网 时间:2024/05/21 10:28
最优贸易简化版
题目描述 C国有 nn 座城市,编号是 11 到 nn ,编号为 ii 的城市有路到编号为 i+1i+1 的城市(编号为 nn
的城市没有路到其他的城市)。
C国幅员辽阔,各地的资源分布情况各不相同,这就导致了同一种商品在不同城市的价格不一定相同。但是,同一种商品在同一个城市的买入价和卖出价始终是相同的。
商人阿龙再次来到C国旅游。他还是想贩卖水晶赚取旅费,在某个城市买入,再另一个城市卖出。
他将从编号为 aa 的城市到编号到 bb 的城市。请你帮他算算,最多能赚多少钱。
注:他最多进行一次买入和一次卖出。
输入 第一行两个整数 nn 和 mm ,表示 nn 个城市和 mm 个询问。
第二行 n个整数,表示 n 座城市水晶的买入和卖出的价格。接下来 mm 行,每行两个整数 a,b ,表示阿龙要从编号为 a的城市到编号为 b的城市(a小于b)
输出 对于每个询问输出阿龙能赚多少钱。
一.并查集
通过离线对询问进行处理,然后由1扫描至n,利用getfa函数对数据进行处理
复杂度为O(n+m)【最快】
#include<cstdio>#include<iostream>#include<vector>using namespace std;#define M 500005#define FOR(i,x,y) for(int i=(x);i<(y);i++)typedef pair<int,int>P;vector<P>q[M];int par[M],mx[M],mi[M],res[M],A[M],ans[M];int getfa(int x){ if(par[x]==x)return x; int t=par[x]; par[x]=getfa(par[x]); if(res[x]<mx[t]-mi[x])res[x]=mx[t]-mi[x]; if(res[x]<res[t])res[x]=res[t]; if(mi[x]>mi[t])mi[x]=mi[t]; if(mx[x]<mx[t])mx[x]=mx[t]; return par[x];}inline void Rd(int &res){ res=0;char c; while(c=getchar(),c<47); do res=(res<<3)+(res<<1)+(c&15); while(c=getchar(),c>=48);}int main(){ int n,m; Rd(n),Rd(m); FOR(i,1,n+1)Rd(A[i]); FOR(i,1,m+1){//离线 int x,y; Rd(x),Rd(y); P t;t.first=x,t.second=i; q[y].push_back(t); } FOR(i,1,n+1){par[i]=i;mx[i]=mi[i]=A[i];}//初始化 FOR(i,1,n+1){ FOR(j,0,q[i].size()){ getfa(q[i][j].first); ans[q[i][j].second]=res[q[i][j].first]; } par[i]=i+1; } FOR(i,1,m+1)printf("%d\n",ans[i]); return 0;}
二.线段树
通用的状态转移方程为:
void up(node &fa,node& l,node& r){ fa.res=max(l.res,r.res); fa.res=max(r.mx-l.mi); fa.mi=min(l.mi,r.mi); fa.mx=max(l.mx,r.mx);}
然后就是裸的线段树,套个模板就好了
三.分块
其实也秉承了线段树up的思想,经过优化n^3/2也可以过
#include<cstdio>#include<cmath>using namespace std;#define FOR(i,x,y) for(int i=(x);i<=(y);i++)#define M 500005int A[M];struct node{ int mx,mi,v;}B[M];void init(int n,int s){ FOR(i,0,n/s){ B[i].mi=1e9; B[i].mx=0; B[i].v=0; } FOR(i,1,n){ if(A[i]-B[i/s].mi>B[i/s].v)B[i/s].v=A[i]-B[i/s].mi; if(B[i/s].mi>A[i])B[i/s].mi=A[i]; if(B[i/s].mx<A[i])B[i/s].mx=A[i]; }}int main(){ int n,m; scanf("%d%d",&n,&m); FOR(i,1,n)scanf("%d",&A[i]); init(n,sqrt(n)); int s=sqrt(n); while(m--){ int x,y; scanf("%d%d",&x,&y); int ka=x/s,kb=y/s,ans=0; if(ka==kb){ int mi=1e9; FOR(i,x,y){ if(A[i]-mi>ans)ans=A[i]-mi; if(A[i]<mi)mi=A[i]; } } else{ int mi=1e9; FOR(i,x,(ka+1)*s-1){ if(A[i]-mi>ans)ans=A[i]-mi; if(A[i]<mi)mi=A[i]; } FOR(i,ka+1,kb-1){ if(B[i].mx-mi>ans)ans=B[i].mx-mi; if(B[i].v>ans)ans=B[i].v; if(B[i].mi<mi)mi=B[i].mi; } FOR(i,kb*s,y){ if(A[i]-mi>ans)ans=A[i]-mi; if(A[i]<mi)mi=A[i]; } } printf("%d\n",ans); } return 0;}
四.倍增
实现起来与分块相似
但复杂度为nlog(n)
贴上部分代码
预处理
FOR(i,1,n){ mx[i][0]=max(A[i],A[i+1]); mi[i][0]=min(A[i],A[i+1]); val[i][0]=max(val[i][0],A[i+1]-A[i]);}FOR(j,1,S-1){ FOR(i,1,n){ if(i+(1<<j-1)>n)continue; mx[i][j]=max(mx[i][j-1],mx[i+(1<<j-1)][j-1]); mi[i][j]=min(mi[i][j-1],mi[i+(1<<j-1)][j-1]); val[i][j]=max(val[i][j-1],val[i+(1<<j-1)][j-1]); val[i][j]=max(val[i][j],mx[i+(1<<j-1)][j-1]-mi[i][j-1]); }}
solve
int len=y-x,mn=1e9,ans=0;FOR(i,0,S-1){ if(len&1<<i){ ans=max(ans,val[x][i]); ans=max(ans,mx[x][i]-mn); mn=min(mn,mi[x][i]); x+=1<<i; }}
阅读全文
1 0
- 最优贸易简化版
- 最优贸易简化版
- 最优贸易
- 最优贸易
- 最优贸易
- 最优贸易
- 最优贸易
- trade 最优贸易
- VIJOS 1754 最优贸易
- 【Spfa】noip2009 最优贸易
- smartoj P1013 最优贸易
- vijosP1754 最优贸易
- 最优贸易解题报告
- [CODEVS 1173] 最优贸易
- [NOIP2009]最优贸易 T3
- vijos-1754 最优贸易
- [NOIP2009][spfa]最优贸易
- 【图论】NOIP2009最优贸易
- C3P0-数据库连接池解读
- OOP和AOP区别
- Ambari升级问题
- fangzhen
- 2017 ACM-ICPC 亚洲区域赛【西安站网赛】Maximum Flow
- 最优贸易简化版
- 系统分析与设计的环境
- 51 nod1051最大和子矩阵
- Python2.7 tab自动补齐
- 2017 ACM-ICPC 亚洲区(西安赛区)网络赛 F Trig Function(数论,组合数)
- bzoj1051 [HAOI2006]受欢迎的牛
- mysql的安装和卸载
- ubuntu mysql 执行sql文件
- bzoj1072 [SCOI2007]排列perm