分块

一直以为分块很高端,学完之后发现其实很简单了

分块查找是折半查找和顺序查找的一种改进方法,分块查找由于只要求索引表是有序的,对块内节点没有排序要求,因此特别适合于节点动态变化的情况。

分块就是将n个数分为每段有√n个数的多个区间,这样我们就可以在几乎O(√n)的时间内完成查找

分块模版

int block,num,belong[100100],le[100100],ri[100100],n;
long long a[100100],max_sum[10100];
void build()
{     int i,j,k;
      block=sqrt(n);
      num=n/block;
      if(n%block)num++;
      for(i=1;i<=num;i++)
         le[i]=ri[i-1]+1,
         ri[i]=ri[i-1]+block;
      if(ri[num]>n)ri[num]=n;
      for(i=1;i<=n;i++)
         belong[i]=(i-1)/block+1;
      for(i=1;i<=num;i++)
         for(j=le[i];j<=ri[i];j++)
            max_sum[i]=max(max_sum[i],a[j]);
}

例题

http://acm.uestc.edu.cn/#/problem/show/1324卿学姐与公主

分块裸题,维护每一块的最大值

代码

#include<iostream>
#include<cstdio>
#include<cstring>
#include<string>
#include<algorithm>
#include<cctype>
#include<cmath>
#include<cstdlib>
#include<queue>
#include<ctime>
#include<vector>
#include<set>
#include<map>
#include<stack>
using namespace std;
int block,num,belong[100100],le[100100],ri[100100],n;
long long a[100100],max_sum[10100];
void build()
{     int i,j,k;
      block=sqrt(n);
      num=n/block;
      if(n%block)num++;
      for(i=1;i<=num;i++)
         le[i]=ri[i-1]+1,
         ri[i]=ri[i-1]+block;
      if(ri[num]>n)ri[num]=n;
      for(i=1;i<=n;i++)
         belong[i]=(i-1)/block+1;
      for(i=1;i<=num;i++)
         for(j=le[i];j<=ri[i];j++)
            max_sum[i]=max(max_sum[i],a[j]);
}
void update(int p,int x)
{     a[p]+=x;
      max_sum[belong[p]]=max(max_sum[belong[p]],a[p]);
}
long long ask(int L,int R)
{     int i,j,k;
      long long maxn=0;
      if(belong[L]==belong[R]){
         for(i=L;i<=R;i++)
            maxn=max(maxn,a[i]);
         return maxn;
         }
         else {
             for(i=L;i<=ri[belong[L]];i++)
                maxn=max(maxn,a[i]);
             for(i=belong[L]+1;i<=belong[R]-1;i++)
                maxn=max(maxn,max_sum[i]);
             for(i=le[belong[R]];i<=R;i++)
                maxn=max(maxn,a[i]);
             return maxn;
         }
}
int main()
{     int q,i,j,k,x,y,p;
      cin>>n>>q;
      build();
      for(i=1;i<=q;i++){
          scanf("%d%d%d",&k,&p,&x);
          if(k==1)update(p,x);
            else printf("%lld\n",ask(p,x));
      }
      return 0;
}

 

 
posted @ 2018-01-23 08:54  水题收割者  阅读(216)  评论(0编辑  收藏  举报