【bzoj1699/USACO2007】Balanced Lineup排队——RMQ问题

题目链接

很明显的求区间最大最小值问题,可以用st表做,不过ccz 大爷教我用zkw线段树来解决这种问题,感觉很好用><

对于1~n的序列,我们先转化成0~n-1,(方便之后的xor),然后求一个最小的mx=(1<<i)使得mx>=n,这样就保证了是一棵满二叉树,叶子结点为0~mx-1。

然后考虑对于每层建立一个数组tr[mx],拿最顶层来说,我们可以把它根据左右子树划分为0~mx/2-1,mx/2~mx-1,这样的话当i<=mx/2-1时,tr[i]即为i~mx/2-1的最大(小)值,当i>=mx/2,时,tr[i]即为mx/2~mx-1的最大(小)值(也就是左后缀,右前缀)。

往下的每一层的数组都类似如此。

当我们需要查询l~r时,现将l--,r--,然后我们要找到lca(l,r),这样的话最大(小)值就是max/min(tr[l],tr[r])。

当然我们并不需要真的去用倍增求lca,仔细观察可以发现,当最底层为第0层的时候,它们的lca就在  l^r的二进制位数-1 那一层。

不过这样的话查询仍是logn的,我们可以先预处理出0~1023的位数,1024~220 的位数我们可以通过log(a/b)=log(a)-log(b)求出。

具体实现细节看代码:

 1 #include<cstdio>
 2 #include<cstring>
 3 #include<algorithm>
 4 const int N=5e4+10;
 5 int a[N],tr[20][N],tr1[20][N];
 6 int wei[1024],ok[1024];
 7 int read(){
 8     int ans=0,f=1;char c=getchar();
 9     while(c<‘0‘||c>‘9‘){if(c==‘-‘)f=-1;c=getchar();}
10     while(c>=‘0‘&&c<=‘9‘){ans=ans*10+c-48;c=getchar();}
11     return ans*f;
12 }
13 int mx=1,h=0;
14 /*-----------------------------------------------------*/
15 void build(int l,int r,int x,int p){
16     if(l==r){tr1[x][r]=tr[x][l]=a[l];return;}
17     if(!p){
18         tr1[x][r]=tr[x][r]=a[r];
19         for(int i=r-1;i>=l;i--){
20             tr[x][i]=std::max(a[i],tr[x][i+1]);
21             tr1[x][i]=std::min(a[i],tr1[x][i+1]);
22         }
23     }
24     else{
25         tr1[x][l]=tr[x][l]=a[l];
26         for(int i=l+1;i<=r;i++){
27             tr[x][i]=std::max(a[i],tr[x][i-1]);
28             tr1[x][i]=std::min(a[i],tr1[x][i-1]);
29         }
30     }
31 }
32 int main(){
33     int n=read(),q=read(),ce=0;wei[0]=0;
34     for(int i=0;i<=9;i++)ok[(1<<i)]=1;
35     for(int i=1;i<=1023;i++)wei[i]=ok[i]?wei[i-1]+1:wei[i-1];
36     do{mx*=2;}while(mx<n);
37     for(int i=0;i<=n-1;i++){
38         a[i]=read();
39     }
40     int ff;
41     for(int i=1;i<=mx>>1;i<<=1){
42         ff=0;
43         for(int j=0;j<n;j+=i){
44             build(j,j+i-1,ce,ff);
45             ff^=1;
46         }
47         ce++;
48     }
49     while(q--){
50         int l=read(),r=read();
51         l--;r--;
52         int x=l^r,p=0;
53         if(x>=1024)p=wei[x/1024]+10;
54         else p=wei[x];
55         if(!p)printf("0\n");
56         else printf("%d\n",std::max(tr[p-1][l],tr[p-1][r])-std::min(tr1[p-1][l],tr1[p-1][r]));
57     }
58     return 0;
59 }

bzoj1699

时间: 2024-10-08 01:00:20

【bzoj1699/USACO2007】Balanced Lineup排队——RMQ问题的相关文章

BZOJ1699: [Usaco2007 Jan]Balanced Lineup排队

1699: [Usaco2007 Jan]Balanced Lineup排队 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 933  Solved: 568[Submit][Status] Description 每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John 决定让一些牛们玩一场飞盘比赛. 他准备找一群在对列中为置连续的牛来进行比赛. 但是为了避免水平悬殊,牛的身高不应该相差太大. Jo

[bzoj 1699] [Usaco2007 Jan]Balanced Lineup排队

传送门:http://www.lydsy.com/JudgeOnline/problem.php?id=1699 [Usaco2007 Jan]Balanced Lineup排队 Time Limit: 5 Sec  Memory Limit: 64 MBSubmit: 1443  Solved: 920[Submit][Status][Discuss] Description 每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John 决定让一

bzoj 1699: [Usaco2007 Jan]Balanced Lineup排队 分块

1699: [Usaco2007 Jan]Balanced Lineup排队 Time Limit: 5 Sec  Memory Limit: 64 MB Description 每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John 决定让一些牛们玩一场飞盘比赛. 他准备找一群在对列中为置连续的牛来进行比赛. 但是为了避免水平悬殊,牛的身高不应该相差太大. John 准备了Q (1 <= Q <= 180,000) 个可能的牛的

[Usaco2007 Jan]Balanced Lineup排队

[Usaco2007 Jan]Balanced Lineup排队 Time Limit: 5 Sec Memory Limit: 64 MB Submit: 2333 Solved: 1424 Description 每天,农夫 John 的N(1 <= N <= 50,000)头牛总是按同一序列排队. 有一天, John 决定让一些牛们玩一场飞盘比赛. 他准备找一群在对列中为置连续的牛来进行比赛. 但是为了避免水平悬殊,牛的身高不应该相差太大. John 准备了Q (1 <= Q &l

POJ 3264 Balanced Lineup(RMQ)

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 36513   Accepted: 17103 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer Joh

P2880 [USACO07JAN]平衡的阵容Balanced Lineup(RMQ的倍增模板)

题面:P2880 [USACO07JAN]平衡的阵容Balanced Lineup RMQ问题:给定一个长度为N的区间,M个询问,每次询问Li到Ri这段区间元素的最大值/最小值. RMQ的高级写法一般有两种,即为线段树(并不很会╥﹏╥...)和ST表(一种利用dp求解区间最值的倍增算法) 定义:maxx[i][j]和minn[i][j]分别表示i到i+2^j-1这段区间的最大值和最小值. 预处理:maxx[i][0]=minn[i][0]=a[i].即i到i区间的最大值.最小值都是a[i]. 状

POJ 题目3264 Balanced Lineup(RMQ)

Balanced Lineup Time Limit: 5000MS   Memory Limit: 65536K Total Submissions: 39046   Accepted: 18291 Case Time Limit: 2000MS Description For the daily milking, Farmer John's N cows (1 ≤ N ≤ 50,000) always line up in the same order. One day Farmer Joh

BZOJ 1699 [Usaco2007 Jan]Balanced Lineup排队 线段树

题意:链接 方法:线段树 解析: 题意即题解. 多次询问区间最大值与最小值的差,显然直接上线段树或者rmq维护区间最值即可. 代码: #include <cstdio> #include <cstring> #include <iostream> #include <algorithm> #define N 50010 #define lson l,mid,rt<<1 #define rson mid+1,r,rt<<1|1 #def

P1699: [Usaco2007 Jan]Balanced Lineup排队

很明显是一道RMQ问题,倍增法,维护一下区域的最大/小值就行了. 1 var n,i,j,q,f,t,times:longint; 2 hmin,hmax:array[0..100,0..50000] of longint; 3 function min(a,b:longint):longint; 4 begin 5 if a>b then exit(b) 6 else exit(a); 7 end; 8 function max(a,b:longint):longint; 9 begin 10