#6278. 数列分块入门 2(询问区间内小于某个值 xx 的元素个数)
题目链接:https://loj.ac/problem/6278
题目大意:中文题目
具体思路:数列分块模板题,对于更新的时候,我们通过一个辅助数组来进行,对于原始的数组,我们只是用来加减,然后这个辅助数组的作用就是对每一块进行排序,当查询的时候,如果不是整块的,我们直接通过a数组来记录,对于整块的,我们直接通过排序的辅助数组进行二分查找就可以了。
注意每一次更新,除了整块的,我们都需要进行对b数组这一整块的重新赋值,因为只是部分赋值的话,b数组已经排序了,这样的话数组的下标对应的数就已经改变了。
lower_bound查询的时候, id=lower_bound(b+l[i],b+r[i]+1,tmp)-(b+l[i]);如果是需要记录小于的个数的话,直接减去b+l[i]就是个数了。
A代码:
1 #include<bits/stdc++.h> 2 using namespace std; 3 # define ll long long 4 const int maxn = 2e5+100; 5 const int mod = 1e8+7; 6 ll l[maxn],r[maxn],belong[maxn]; 7 ll add[maxn],a[maxn],b[maxn]; 8 int n; 9 void buildblock() 10 { 11 ll tmp=(ll)sqrt(n); 12 ll tot=n/tmp; 13 if(n%tmp) 14 tot++; 15 for(ll i=1; i<=n; i++) 16 { 17 belong[i]=(i-1)/tmp+1ll; 18 } 19 for(ll i=1; i<=tot; i++) 20 { 21 l[i]=(i-1)*tmp+1ll; 22 r[i]=i*tmp; 23 } 24 r[tot]=n; 25 for(ll i=1; i<=tot; i++) 26 { 27 sort(b+l[i],b+r[i]+1); 28 } 29 } 30 void init(int tmp){ 31 for(int i=l[tmp];i<=r[tmp];i++)b[i]=a[i]; 32 sort(b+l[tmp],b+r[tmp]+1); 33 } 34 void update(ll st,ll ed,ll val) 35 { 36 if(belong[st]==belong[ed]) 37 { 38 for(ll i=st; i<=ed; i++)a[i]+=val; 39 init(belong[st]); 40 return ; 41 } 42 for(ll i=st; i<=r[belong[st]]; i++)a[i]+=val; 43 init(belong[st]); 44 for(ll i=l[belong[ed]]; i<=ed; i++)a[i]+=val; 45 init(belong[ed]); 46 for(ll i=belong[st]+1; i<belong[ed]; i++) 47 add[i]+=val; 48 } 49 ll ask(ll st,ll ed,ll val) 50 { 51 ll ans=0; 52 if(belong[st]==belong[ed]) 53 { 54 for(ll i=st; i<=ed; i++) 55 { 56 if(a[i]+add[belong[st]]<val) 57 ans++; 58 } 59 return ans; 60 } 61 for(ll i=st; i<=r[belong[st]]; i++) 62 { 63 ans+=(a[i]+add[belong[st]]<val?1:0); 64 } 65 for(ll i=l[belong[ed]]; i<=ed; i++) 66 { 67 ans+=(a[i]+add[belong[ed]]<val?1:0); 68 } 69 for(ll i=belong[st]+1; i<belong[ed]; i++) 70 { 71 ll tmp=val-add[i]; 72 ll id=lower_bound(b+l[i],b+r[i]+1,tmp)-(b+l[i]); 73 ans+=id; 74 } 75 return ans; 76 } 77 int main() 78 { 79 // freopen("hqx.in","r",stdin); 80 scanf("%d",&n); 81 for(int i=1; i<=n; i++) 82 { 83 scanf("%lld",&a[i]); 84 b[i]=a[i]; 85 } 86 buildblock(); 87 ll op,st,ed; 88 ll val; 89 while(n--) 90 { 91 scanf("%lld %lld %lld %lld",&op,&st,&ed,&val); 92 if(op==0) 93 { 94 update(st,ed,val); 95 } 96 else if(op==1) 97 { 98 printf("%lld\n",ask(st,ed,val*val)); 99 } 100 } 101 return 0; 102 }