POJ

这个题目是一个典型的RMQ问题,给定一个整数序列,1~N,然后进行Q次询问,每次给定两个整数A,B,(1<=A<=B<=N),求给定的范围内,最大和最小值之差。

解法一:这个是最初的解法,时间上可能会超时,下面还有改进算法.4969ms

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #define INF 1000010
 4 #define max(a,b) ((a)>(b)?(a):(b))
 5 #define min(a,b) ((a)>(b)?(b):(a))
 6 
 7 typedef struct res
 8 {
 9     int mx,mi;
10 } pair;
11 
12 typedef struct node
13 {
14     struct node *lc,*rc;
15     int ld,rd;
16     pair res;
17 }  node;
18 
19 node *buildTree(int a,int b)
20 {
21     node*p=(node*)malloc(sizeof(node));
22     p->ld=a;
23     p->rd=b;
24     p->res.mx=0;
25     p->res.mi=INF;
26     p->lc=p->rc=NULL;
27     if(a==b)
28         return p;
29     p->lc=buildTree(a,(a+b)>>1);
30     p->rc=buildTree(((a+b)>>1)+1,b);
31     return p;
32 }
33 
34 void insert(node*T,int pos,int key)
35 {
36     int mid=(T->rd+T->ld)>>1;
37     if(T->rd==T->ld)
38     {
39         T->res.mx=T->res.mi=key;
40         return;
41     }
42     if(pos<=mid)
43         insert(T->lc,pos,key);
44     else insert(T->rc,pos,key);
45     T->res.mx=max(T->lc->res.mx,T->rc->res.mx);
46     T->res.mi=min(T->lc->res.mi,T->rc->res.mi);
47     return;
48 }
49 
50 pair search(node*T,int a,int b)
51 {
52     pair  temp1,temp2,ans;
53     int mid=(T->rd+T->ld)>>1;
54 
55     temp1.mx=temp2.mx=0;
56     temp1.mi=temp2.mi=INF;
57     if(a<=T->ld&&T->rd<=b)
58         return T->res;
59     if(a<=mid)
60         temp1=search(T->lc,a,b);
61     if(b>mid)
62         temp2=search(T->rc,a,b);
63     ans.mx=max(temp1.mx,temp2.mx);
64     ans.mi=min(temp1.mi,temp2.mi);
65     return ans;
66 }
67 
68 int main(void)
69 {
70     int n,q,i,a,b;
71     pair ans;
72     scanf("%d%d",&n,&q);
73     node *head=buildTree(1,n);
74     for(i=1; i<=n; i++)
75     {
76         scanf("%d",&a);
77         insert(head,i,a);
78     }
79     for(i=1; i<=q; i++)
80     {
81         scanf("%d%d",&a,&b);
82         ans=search(head,a,b);
83         printf("%d
",ans.mx-ans.mi);
84     }
85     return 0;
86 }

解法二:

利用数组的形式:3704ms

 1 #include<stdio.h>
 2 #include<stdlib.h>
 3 #include<string.h>
 4 #define N 1000010
 5 #define INF 1000010
 6 #define max(a,b) ((a)>(b)?(a):(b))
 7 #define min(a,b) ((a)>(b)?(b):(a))
 8 
 9 int l[N],r[N],i,n;
10 typedef struct
11 {
12     int mx,mi;
13 } pair;
14 pair res[N];
15 
16 void BuildTree(int x,int y,int p)
17 {
18     l[p]=x;
19     r[p]=y;
20     if(x==y)
21         return;
22     BuildTree(x,(x+y)>>1,2*p);
23     BuildTree(((x+y)>>1)+1,y,2*p+1);
24 }
25 
26 void Insert(int num,int p)
27 {
28     int mid=(l[p]+r[p])>>1;
29     res[p].mx=max(res[p].mx,num);
30     res[p].mi=min(res[p].mi,num);
31     if(l[p]==r[p])
32         return;
33     if(i<=mid)
34         Insert(num,2*p);
35     else Insert(num,2*p+1);
36 }
37 
38 pair search(int x,int y,int p)
39 {
40     pair a1,a2,ans;
41     a1.mx=a2.mx=0;
42     a1.mi=a2.mi=INF;
43     int mid=(l[p]+r[p])>>1;
44     if(x<=l[p]&&y>=r[p])
45         return res[p];
46     if(x<=mid)
47     a1=search(x,y,2*p);
48     if(y>mid)
49     a2=search(x,y,2*p+1);
50     ans.mx=max(a1.mx,a2.mx);
51     ans.mi=min(a1.mi,a2.mi);
52     return ans;
53 }
54 
55 int main(void)
56 {
57     int q,j,x,y;
58     pair ans;
59     memset(res,0,sizeof(res));
60     scanf("%d%d",&n,&q);
61     BuildTree(1,n,1);
62     for(i=0; i<N; i++)
63         res[i].mi=INF;
64     for(i=1; i<=n; i++)
65     {
66         scanf("%d",&j);
67         Insert(j,1);
68     }
69 
70     for(i=0; i<q; i++)
71     {
72         scanf("%d%d",&x,&y);
73         ans=search(x,y,1);
74         printf("%d
",ans.mx-ans.mi);
75     }
76     return 0;
77 }

 解法三:

这是利用别人的算法改进而来,所以有时候多借鉴别人的代码,并且可以和自己的想法结合起来,效果还不错.

 1 #include<stdio.h>
 2 #include<string.h>
 3 #include<stdlib.h>
 4 #define N 50010
 5 #define INF 1000010
 6 #define max(a,b) ((a)>(b)?(a):(b))
 7 #define min(a,b) ((a)>(b)?(b):(a))
 8 
 9 typedef struct
10 {
11     int l,r;
12     int mx,mi;
13 } pair;
14 pair temp[N*3];
15 int Max,Min;
16 
17 void BuildTree(int x,int y,int p)
18 {
19     temp[p].l=x;
20     temp[p].r=y;
21     temp[p].mx=0;
22     temp[p].mi=INF;
23     if(x==y)
24         return;
25     int mid=(x+y)/2;
26     BuildTree(x,mid,p*2);
27     BuildTree(mid+1,y,2*p+1);
28 }
29 
30 void Insert(int v,int num,int p)
31 {
32     if(temp[v].l==temp[v].r)
33     {
34         temp[v].mx=temp[v].mi=num;
35         return ;
36     }
37     int mid=(temp[v].r+temp[v].l)/2;
38     if(p<=mid)
39     {
40         Insert(2*v,num,p);
41         temp[v].mx=max(temp[v].mx,temp[2*v].mx);
42         temp[v].mi=min(temp[v].mi,temp[2*v].mi);
43     }
44     else
45     {
46         Insert(2*v+1,num,p);
47         temp[v].mx=max(temp[v].mx,temp[2*v+1].mx);
48         temp[v].mi=min(temp[v].mi,temp[2*v+1].mi);
49     }
50 }
51 
52 void search(int x,int y,int p)
53 {
54     if(temp[p].l==x&&temp[p].r==y)
55     {
56         Max=max(Max,temp[p].mx);
57         Min=min(Min,temp[p].mi);
58         return;
59     }
60     int mid=(temp[p].l+temp[p].r)/2;
61     if(x>mid)
62     {
63         search(x,y,2*p+1);
64     }
65     else if(y<=mid)
66     {
67         search(x,y,2*p);
68     }
69     else
70     {
71         search(x,mid,2*p);
72         search(mid+1,y,2*p+1);
73     }
74     return;
75 }
76 
77 int main(void)
78 {
79     int n,q,i,x,y;
80     scanf("%d%d",&n,&q);
81     BuildTree(1,n,1);
82     for(i=1;i<=n;i++)
83     {
84         scanf("%d",&x);
85         Insert(1,x,i);
86     }
87     for(i=0;i<q;i++)
88     {
89         scanf("%d%d",&x,&y);
90         Max=0;
91         Min=INF;
92         search(x,y,1);
93         printf("%d
",Max-Min);
94     }
95     return 0;
96 }
原文地址:https://www.cnblogs.com/rootial/p/3204185.html