高级的暴力(一)——分块
在某大佬的帮助下我今天get到了分块
简单来说分块就是可以把块分成某些奇怪的大小,使之达到优秀的复杂度。but我现在只会把块分成根号大小,然后我们修改一个点的
信息时就可以顺便修改次点所在块的信息(O(1))。接着当我们查询[L,R]这段区间,的时候,对于中间的大块可以直接拿来用,对于两
边不完整的块则直接暴力查询(都是根号n,)。
差不多就这样,最后附上DCOJ 1324用分块过的代码
- #include<iostream>
- #include<cstdio>
- #include<cstring>
- #include<algorithm>
- #include<cmath>
- using namespace std;
- const int maxn=1e5+7;
- int num,block,l[maxn],r[maxn],n,m,p,x,t,belong[maxn];
- long long Max[maxn],a[maxn];
- void build()
- {
- block=sqrt(n);//块的太小
- num=n/block;
- if(n%block) num++;//块的个数,记得特判
- for(int i=1;i<=num;i++)
- {
- l[i]=(i-1)*block+1;
- r[i]=i*block;
- }//确定每个块的左右区间
- r[num]=n;//不要忘记最右为n
- for(int i=1;i<=n;i++) belong[i]=(i-1)/block+1;//确定每个 点所属的块
- for(int i=1;i<=num;i++)
- for(int j=l[i];j<=r[i];j++)
- Max[i]=max(Max[i],a[j]);//预处理
- }
- void update(int x,int date)//单点更改
- {
- a[x]+=date;
- Max[belong[x]]=max(Max[belong[x]],a[x]);
- }
- long long ask(int x,int y)//区间查询
- {
- long long ans=0;
- if(belong[x]==belong[y])
- {
- for(int i=x;i<=y;i++)
- {
- ans=max(ans,a[i]);
- }
- return ans;
- }//如果左右端点在同一块内则直接暴力查询
- for(int i=x;i<=r[belong[x]];i++)
- ans=max(ans,a[i]);
- for(int i=belong[x]+1;i<belong[y];i++)
- ans=max(ans,Max[i]);//如果左右端点需跨块,那么对于中间大块的信息直接使用
- for(int i=l[belong[y]];i<=y;i++)
- ans=max(ans,a[i]);// 两端不完整的的块暴力查询
- return ans;
- }
- int main()
- {
- scanf("%d",&n);
- build();
- scanf("%d",&m);
- while(m--)
- {
- scanf("%d%d%d",&t,&p,&x);
- if(t==1) update(p,x);
- else printf("%lld\n",ask(p,x));
- }
- return 0;
- }