#数列分块入门 2
这道题他们说不用分块就用平衡树,所以暴力拆解就用分块。
做了两道分块已经渐渐明白分块的一些模板在这里就放一下吧(用vector比用数组md方便多了)
1 void /*修改操作*//*查询操作*/ (int l,int r.....,int val)/*修改的要素*/ 2 { 3 /*总是先修改(查询)角区间,就是那种不是整块整块的*/ 4 for(int i=l;i<=(id[l],n)/*注意结束的区间可能就是 l~r 所以取min*/;i++) 5 { 6 /*暴力枚举修改(查询)*/ 7 } 8 if(/* l 和 r 不在同一个区间 就把 r 所在的角区间枚举修改(查询)*/) 9 { 10 /*暴力~*/ 11 /*但是能二分或者别的什么能搞出来,那肯定换一下啦*/ 12 } 13 /*最后就整块整块的枚举啦*/ 14 }
这道题就是维护每个块内的元素成单调的,这样最后查询的时候就可以用二分(lower_bound)来进行查询会快很多,而剩下的就只有暴力、暴力再暴力。
1 #include<bits/stdc++.h> 2 using namespace std; 3 int n; 4 int block; 5 int id[50009]; 6 int num[50009]; 7 int tag[10009]; 8 vector<int>v[10009]; 9 inline long long kd() 10 { 11 long long x=0,f=1;char ch=getchar(); 12 while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();} 13 while(ch>='0'&&ch<='9'){x=x*10+(ch^48);ch=getchar();} 14 return x*f; 15 } 16 inline void reset(int now) 17 { 18 int r=min(id[now]*block,n); 19 v[id[now]].clear();/*清空*/ 20 for(int i=(id[now]-1)*block+1;i<=r;i++)v[id[i]].push_back(num[i]);/*挼进去*/ 21 sort(v[id[now]].begin(),v[id[now]].end());/*排个序*/ 22 } 23 inline void add(int l,int r,int c) 24 { 25 int minn=min(r,id[l]*block); 26 for(int i=l;i<=minn;i++)num[i]+=c;/*暴力修改角区间*/ 27 reset(l);/*同下面reset的注释*/ 28 if(id[l]!=id[r])/*如果 l 和 r 不在个区间之内*/ 29 { 30 for(int i=(id[r]-1)*block+1;i<=r;i++)num[i]+=c;/*同样暴力*/ 31 reset(r);/*角区间进行修改之后就打乱的顺序,所以重新排序*/ 32 } 33 for(int i=id[l]+1;i<=id[r]-1;i++)tag[i]+=c;/*直接用tag来修改整块区间*/ 34 } 35 int query(int l,int r,int c) 36 { 37 int ans=0; 38 int minn=min(r,id[l]*block); 39 for(int i=l;i<=minn;i++) 40 if(num[i]+tag[id[i]]<c)ans++;/*暴力枚举角区间*/ 41 if(id[l]!=id[r]) 42 { 43 for(int i=(id[r]-1)*block+1;i<=r;i++) 44 { 45 if(num[i]+tag[id[i]]<c)ans++;/*再次暴力枚举*/ 46 } 47 } 48 for(int i=id[l]+1;i<=id[r]-1;i++) 49 { 50 int x=c-tag[i]; 51 ans+=lower_bound(v[i].begin(),v[i].end(),x)-v[i].begin();/*整块的就直接二分查找*/ 52 } 53 return ans; 54 } 55 int main() 56 { 57 n=kd(); 58 for(int i=1;i<=n;i++)num[i]=kd(); 59 block=(int)sqrt(n); 60 for(int i=1;i<=n;i++) 61 { 62 id[i]=(i-1)/block+1; 63 v[id[i]].push_back(num[i]); 64 } 65 for(int i=1;i<=id[n];i++) 66 sort(v[i].begin(),v[i].end()); 67 for(int i=1;i<=n;i++) 68 { 69 int opt=kd(); 70 int l=kd(),r=kd(),c=kd(); 71 if(opt==0)add(l,r,c); 72 if(opt==1)cout<<query(l,r,c*c)<<endl; 73 } 74 return 0; 75 }