题目链接
分块:
O(sqrt(n))时间复杂度
过区间寻求最大值
分块题解:
将区间分为
sqrt(n)
大小的ceil(n/sqrt(n))
块, 用ma[ ]
数组存每一块的最大值,当修改的时候我们把分的块的最大值修改,如果可以修改,查询的时候就先暴力查询边角的最大值,然后在和中间的块即可
AC代码:
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
const int maxn=5e5+5;
const int siz=2e3+5;
int a[maxn],pos[maxn],ma[siz],l[maxn],r[maxn];
void pushup(int p,int w)//改变每一块的最大值
{
a[p]=w;
ma[pos[p]]=max(ma[pos[p]],a[p]);
}
int query(int lx,int rx)//询问
{
int blc=pos[lx];
int blk=pos[rx];
int maxx=0;
if(blc==blk)
{
for(int i=lx; i<=rx; i++)
{
maxx=max(a[i],maxx);
}
}
else
{
for(int i=lx; i<=r[blc]; i++)
{
maxx=max(maxx,a[i]);
}
for(int i=blc+1; i<=blk-1; i++)
{
maxx=max(ma[i],maxx);
}
for(int i=l[blk]; i<=rx; i++)
{
maxx=max(maxx,a[i]);
}
}
//printf("%d\n",maxx);
return maxx;
}
int main()
{
int n,q;
while(~scanf("%d %d",&n,&q))
{
memset(ma,0,sizeof(ma));
int dis=sqrt(n);
int num=ceil(n*1.0/dis);
for(int i=1; i<=num; i++) //求每一块的上下区间
{
l[i]=(i-1)*dis;
r[i]=i*dis;
}
r[num]=n;
for(int i=1; i<=n; i++) //每一块的最大值
{
scanf("%d",&a[i]);
pos[i]=(i-1)/dis+1;
ma[pos[i]]=max(ma[pos[i]],a[i]);
}
while(q--)
{
char s[10];
int lx,rx;
scanf("%s %d %d",s,&lx,&rx);
if(s[0]=='Q')
{
printf("%d\n",query(lx,rx));
}
else
{
pushup(lx,rx);
}
}
}
}