這道題他們說不用分塊就用平衡樹,因此暴力拆解就用分塊。c++
作了兩道分塊已經漸漸明白分塊的一些模板在這裏就放一下吧(用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)來進行查詢會快不少,而剩下的就只有暴力、暴力再暴力。spa
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 }