Series block topic No.2
Block application and promotion
If you don’t know how to block, please learn “block 1” first->Click here to learn
Put on question number – LOJ 6278 block entry 2
Link up- https://loj.ac/problem/6278
Question surface – give a sequence of numbers, 2 operations, interval addition and ask the number of elements less than a certain value in the interval
Now, get to the point
The difference between this question and that of block 1 is that the single point query becomes an interval query for the number of elements less than a certain value
It’s very difficult. The sequence is out of order. If you compare one by one, O (n ^ 2) will definitely exceed the time limit. If you disrupt the original order, you can’t find the given range of the topic
At this time, the block was put into use again, and the core idea of “large section maintenance, small section simplicity” is still the same
But how to “maintain large sections”? Since we can’t sort the entire sequence, we might as well sort each block. Look at the data. At 50000 level, the sort of O (n * logn) can meet the demand.
void reset(int x){
ve[x].clear();
for(int i=(x-1)*blo+1;i<=min(x*blo,N);i++)
ve[x].push_back(v[i]);
sort(ve[x].begin(),ve[x].end());
//For a block modification and sorting (since the elements in the vector cannot be modified, they are reset and then put in again)
}
After sorting, it is clear that for each block, we use o (logn) binary search (lower)_ Bound function) to find the number of elements less than a certain value.
for(int i=bl[a]+1;i<=bl[b]-1;i++){
Int x = c-atag [i]; // first subtract the interval unified amount, reflecting the micro promotion macro
ans+=lower_ Bound (VE [i]. Begin(), ve [i]. End(), x) - ve [i]. Begin(); // binary search for quantity
}
“Simple paragraph” means that the head and tail are less than a block, and the method of comparison is used one by one
for(int i=a;i<=min(bl[a]*blo,b);i++)
if(v[i]+atag[bl[a]]<c)
ans++;
if(bl[a]!=bl[b])
for(int i=(bl[b]-1)*blo+1;i<=b;i++)
if(v[i]+atag[bl[b]]<c)
ans++;
Interval addition is basically the same as before. If you don’t know, you can refer to “sequence block 1”->Click here to learn
But remember to sort after “segment maintenance”
for(int i=a;i<=min(bl[a]*blo,b);i++)
v[i]+=c;
Reset (BL [a]); // after a single point of modification is made in the "small section", remember to sort the block modifications
if(bl[a]!=bl[b]){
for(int i=(bl[b]-1)*blo+1;i<=b;i++)
v[i]+=c;
Reset (BL [b]); // the same thing
}
Here is the end of the basic ~ finally attached with the complete code (c + +) and carefully designed comments
//LOJ 6278 - sequence block exercise 2
// https://loj.ac/problem/6278
//Vector
#include<bits/stdc++.h>
#define ll long long
using namespace std;
int N,blo;
int v[50005],bl[50005],atag[50005];
vector<int> ve[505];
void reset(int x){
ve[x].clear();
for(int i=(x-1)*blo+1;i<=min(x*blo,N);i++)
ve[x].push_back(v[i]);
sort(ve[x].begin(),ve[x].end());
//For a block modification and sorting (since the elements in the vector cannot be modified, they are reset and then put in again)
}
void add(int a,int b,int c){
for(int i=a;i<=min(bl[a]*blo,b);i++)
v[i]+=c;
Reset (BL [a]); // after a single point of modification is made in the "small section", remember to sort the block modifications
if(bl[a]!=bl[b]){
for(int i=(bl[b]-1)*blo+1;i<=b;i++)
v[i]+=c;
Reset (BL [b]); // the same thing
}
for(int i=bl[a]+1;i<=bl[b]-1;i++)
atag[i]+=c;
}
int query(int a,int b,int c){
int ans=0;
for(int i=a;i<=min(bl[a]*blo,b);i++)
if(v[i]+atag[bl[a]]<c)
ans++;
//On the left, there is less than one piece of "simplicity"
if(bl[a]!=bl[b])
for(int i=(bl[b]-1)*blo+1;i<=b;i++)
if(v[i]+atag[bl[b]]<c)
ans++;
//Right
for(int i=bl[a]+1;i<=bl[b]-1;i++){
Int x = c-atag [i]; // first subtract the interval unified amount, reflecting the micro promotion macro
ans+=lower_ Bound (VE [i]. Begin(), ve [i]. End(), x) - ve [i]. Begin(); // binary search for quantity
}
return ans;
}
int main(){
ios::sync_with_stdio(false);
cin.tie(0);
cin >> N;
blo=sqrt(N);
for(int i=1;i<=N;i++)
cin >> v[i];
for(int i=1;i<=N;i++){
bl[i]=(i-1)/blo+1;
ve[bl[i]].push_back(v[i]);
}
for(int i=1;i<=bl[N];i++)
sort(ve[i].begin(),ve[i].end());
for(int i=1;i<=N;i++){
int F, L, R, C;
cin >> F >> L >> R >> C;
If (F = = 0) add (L, R, c); // interval addition
If (F = = 1) cout < < query (L, R, c * c) < endl; // interval query
}
return 0;
}
If you have any questions, please put them in the comments section below