【线段树】登山climb
来源:互联网 发布:读懂中国经济数据 编辑:程序博客网 时间:2024/05/16 07:50
题目描述
有一座延绵不断、跌宕起伏的山,最低处海拔为0米,最高处海拔不超过8848米。从这座山的一端走到另一端的过程中,每走 1 米海拔高度就升高 1 米或者降低 1 米。有 Q 个登山队计划在这座山的不同区段登山,当他们攀到各自区段内的最高峰时,就会插上他们的队旗。请你写一个程序找出他们插旗的高度。输入
第一行为 N(N≤10^6 ),表示山两端的跨度。接下来 N+1 行,每行一个非负整数Hi (i=0..N),表示该位置的海拔高度(单位:米),其中 H0=Hn=0。然后是一个正整数Q(Q≤7000),表示登山队的数量。紧跟的Q行,每行两个数Ai和Bi,表示第 i 个登山队攀爬的区段[Ai,Bi],其中0≤Ai≤Bi≤N。- 输出
共Q行,每行一个整数,表示第 i 个登山队攀爬区段中最高点的高度。 - 样例输入
10
0
1
2
3
2
3
4
3
2
1
0
5
0 10
2 4
3 7
7 9
8 8
- 样例输出
4
3
4
3
2
这就是个裸的RMQ 用线段树也可以,但是这不是重点。。。
先上代码
1 . 正常线段树
#include <iostream> #include <cstdio> #include <vector> #include <climits> #include <cstdlib> using namespace std; int a[1000000]={0}; int n,k; struct treenode { int left,middle,right; int maxx,minn; treenode *lchild; treenode *rchild; }; treenode* build_tree(int l,int r) { treenode *node=new treenode(); int mid=(l+r)>>1; node->middle=mid; node->left=l; node->right=r; node->lchild=NULL; node->rchild=NULL; if(r-l==1) { node->maxx=a[l];node->minn=a[l];return node; } node->lchild=build_tree(l,mid); node->rchild=build_tree(mid,r); node->maxx=max(node->lchild->maxx,node->rchild->maxx); node->minn=min(node->lchild->minn,node->rchild->minn); return node; } int query(treenode *node,int l,int r) { if((l==node->left)&&(r==node->right)) return node->maxx; if(l>=node->middle) return query(node->rchild,l,r); if(r<=node->middle) return query(node->lchild,l,r); else return max(query(node->lchild,l,node->middle),query(node->rchild,node->middle,r)); } int main() { int n,m; scanf("%d",&n); for(int i=0;i<=n;i++) { scanf("%d",&a[i]); } treenode *root=build_tree(0,n+1); scanf("%d",&m); for(int i=1;i<=m;i++) { int x,y; scanf("%d%d",&x,&y); int temp=query(root,x,y+1); printf("%d\n",temp); } return 0; }
2 . ZKW线段树
#include <iostream>#include <string.h>#include <stdio.h>using namespace std;const int N=100005;int M;int T[4*N];void PushUP(int rt){ T[rt]=max(T[rt<<1],T[rt<<1|1]);}void Build(int n){ for(M=1; M<=n+1; M<<=1); for(int i=M+1; i<=M+n+1; i++) scanf("%d",&T[i]); for(int i=M-1; i>0; i--) PushUP(i);}void Add(int n,int v){ for(T[n+=M]=v,n>>=1; n; n>>=1) PushUP(n);}int Query(int s,int t){ int ans=0; for(s=s+M-1,t=t+M+1; s^t^1; s>>=1,t>>=1) { if(~s&1) ans=max(T[s^1],ans); if(t&1) ans=max(T[t^1],ans); } return ans;}int main(){ freopen("climb.in","r",stdin); freopen("climb.out","w",stdout); char str[15]; int n,t,a,b,k=1,m; scanf("%d",&n); Build(n); scanf("%d",&m); for(int i=1;i<=m;i++) { scanf("%d%d",&a,&b); printf("%d\n",Query(a+1,b+1)); } return 0;}
3 . RMQ
#include<cmath>#include<iostream>#include<cstdio>using namespace std;#define max(a,b) a>b?a:b#define min(a,b) a>b?b:a#define MAX 1000001int a[MAX], dpmax[MAX][20];void RMQ(int N){ int i, j; for(i=1; i<=N; i++) { dpmax[i][0] = a[i]; } for(j=1; j<=log(N+1.0)/log(2.0); j++) for(i=1; i<=N-(1<<j)+1; i++) dpmax[i][j] = max(dpmax[i][j-1], dpmax[i+(1<<(j-1))][j-1]);}int main(){ int N, Q, i, j, k, aa, bb; scanf("%d", &N); for(i=1; i<=N+1; i++) scanf("%d", &a[i]); RMQ(N+1); scanf("%d",&Q); while(Q--) { scanf("%d%d", &i, &j);i++,j++; k = log(j - i + 1.0) / log(2.0); aa = max(dpmax[i][k], dpmax[j-(1<<k)+1][k]); printf("%d\n", aa); } return 0;}
RMQ超时了两个点,估计是写挂了,代码先挂上,不要粘去水题哦、
重点是什么来着???
哦对,这题普通线段树写最后两个点1.2秒左右,然而我大重口味(ZKW)线段树只用0.1秒。。秒出哦。。。。。代码还够短哈哈
0 0
- 【线段树】登山climb
- 《登山》
- 登山
- 登山
- 登山
- 登山
- 登山
- 登山
- 登山
- 登山
- 登山登山... ...
- Climb Stairs
- climb stairs
- 周末登山
- 登山语录
- 登山成仙
- 登山成仙
- 登山成仙
- hdu5673 Robot
- 完美解决Hibernate与MySQL中文乱码问题
- UVA - 10115 Automatic Editing(体现c++STL处理字符串的能力)
- Android Studio中拦截电话的方法
- 堆排序
- 【线段树】登山climb
- Javascript
- 1003 pie
- Redhat中安装rsync
- 数组排序
- 数据结构--二叉堆与堆排序
- 转。。。学嵌入式
- 腾讯云服务器完美解决无法使用公网IP访问的问题
- increment/decrement/dereference操作符