[USACO07JAN]Balanced Lineup

OJ题号:
洛谷2880

思路1:

线段树维护区间最大最小值。

 1 #include<cstdio>
 2 #include<cctype>
 3 #include<utility>
 4 #include<algorithm>
 5 inline int getint() {
 6     char ch;
 7     bool sgn=false;
 8     while(!isdigit(ch=getchar())) if(ch=='-') sgn=true;
 9     int x=ch^'0';
10     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
11     return sgn?-x:x;
12 }
13 const int inf=0x7fffffff;
14 const int N=50001;
15 class SegmentTree {
16     #define _left <<1
17     #define _right <<1|1
18     private:
19         int max[N<<2],min[N<<2];
20         void push_up(const int p) {
21             max[p]=std::max(max[p _left],max[p _right]);
22             min[p]=std::min(min[p _left],min[p _right]);
23         }
24     public:
25         void build(const int p,const int b,const int e) {
26             if(b==e) {
27                 max[p]=min[p]=getint();
28                 return;
29             }
30             int mid=(b+e)>>1;
31             build(p _left,b,mid);
32             build(p _right,mid+1,e);
33             push_up(p);
34         }
35         std::pair<int,int> query(const int p,const int b,const int e,const int l,const int r) {
36             if((b==l)&&(e==r)) {
37                 return std::make_pair(max[p],min[p]);
38             }
39             int mid=(b+e)>>1;
40             int max=0,min=inf;
41             if(l<=mid) {
42                 std::pair<int,int> tmp=query(p _left,b,mid,l,std::min(mid,r));
43                 max=std::max(max,tmp.first);
44                 min=std::min(min,tmp.second);
45             }
46             if(r>mid) {
47                 std::pair<int,int> tmp=query(p _right,mid+1,e,std::max(mid+1,l),r);
48                 max=std::max(max,tmp.first);
49                 min=std::min(min,tmp.second);
50             }
51             return std::make_pair(max,min);
52         }
53 };
54 SegmentTree t;
55 int main() {
56     int n=getint(),m=getint();
57     t.build(1,1,n);
58     while(m--) {
59         int l=getint(),r=getint();
60         std::pair<int,int> tmp=t.query(1,1,n,l,r);
61         printf("%d
",tmp.first-tmp.second);
62     }
63     return 0;
64 } 

 思路2:
倍增法求RMQ。

 1 #include<cmath>
 2 #include<cstdio>
 3 #include<cctype>
 4 #include<algorithm>
 5 inline int getint() {
 6     char ch;
 7     while(!isdigit(ch=getchar()));
 8     int x=ch^'0';
 9     while(isdigit(ch=getchar())) x=(((x<<2)+x)<<1)+(ch^'0');
10     return x;
11 }
12 const int N=50001,logN=log2(N)+1;
13 int min[N][logN],max[N][logN];
14 int main() {
15     int n=getint(),m=getint();
16     for(int i=1;i<=n;i++) {
17         min[i][0]=max[i][0]=getint();
18     }
19     for(int j=1;j<=log2(n);j++) {
20         for(int i=1;i<=n-(1<<j)+1;i++) {
21             min[i][j]=std::min(min[i][j-1],min[i+(1<<(j-1))][j-1]);
22             max[i][j]=std::max(max[i][j-1],max[i+(1<<(j-1))][j-1]);
23         }
24     }
25     while(m--) {
26         int l=getint(),r=getint();
27         int k=log2(r-l+1);
28         printf("%d
",std::max(max[l][k],max[r+1-(1<<k)][k])-std::min(min[l][k],min[r+1-(1<<k)][k]));
29     }
30     return 0;
31 }
原文地址:https://www.cnblogs.com/skylee03/p/7396805.html