LOJ #6278. 数列分块入门 2-分块(区间加法、查询区间内小于某个值x的元素个数)
题目描述
给出一个长为 nn 的数列,以及 nn 个操作,操作涉及区间加法,询问区间内小于某个值 xx 的元素个数。
输入格式
第一行输入一个数字 nn。
第二行输入 nn 个数字,第 ii 个数字为 a_iai,以空格隔开。
接下来输入 nn 行询问,每行输入四个数字 \mathrm{opt}opt、ll、rr、cc,以空格隔开。
若 \mathrm{opt} = 0opt=0,表示将位于 [l, r][l,r] 的之间的数字都加 cc。
若 \mathrm{opt} = 1opt=1,表示询问 [l, r][l,r] 中,小于 c^2c2 的数字的个数。
输出格式
对于每次询问,输出一行一个数字表示答案。
样例
样例输入
4
1 2 2 3
0 1 3 1
1 1 3 2
1 1 4 1
1 2 3 2
样例输出
3
0
2
数据范围与提示
对于 100\%100% 的数据,1 \leq n \leq 50000, -2^{31} \leq \mathrm{others}1≤n≤50000,−231≤others、\mathrm{ans} \leq 2^{31}-1ans≤231−1。
代码:
//#6278. 数列分块入门 2-区间加法,查询区间内小于某个值x的元素个数 #include<bits/stdc++.h> using namespace std; typedef long long ll; const int maxn=5e4+10; int n,m; ll a[maxn],b[maxn],pos[maxn],tag[maxn]; void rechange(int x) { for(int i=(x-1)*m+1;i<=min(x*m,n);i++){ b[i]=a[i]; } sort(b+(x-1)*m+1,b+min(x*m,n)+1); } void update(int l,int r,ll c) { if(pos[l]==pos[r]){ for(int i=l;i<=r;i++) a[i]+=c; rechange(pos[l]); } else{ for(int i=l;i<=pos[l]*m;i++) a[i]+=c; rechange(pos[l]); for(int i=pos[l]+1;i<=pos[r]-1;i++) tag[i]+=c; for(int i=(pos[r]-1)*m+1;i<=r;i++) a[i]+=c; rechange(pos[r]); } } int getnum(int l,int r,int c) { int num=0; if(pos[l]==pos[r]){ for(int i=l;i<=r;i++){ if(a[i]+tag[pos[l]]<c) num++; } } else{ for(int i=l;i<=pos[l]*m;i++){ if(a[i]+tag[pos[l]]<c) num++; } for(int i=pos[l]+1;i<=pos[r]-1;i++){ int cnt=c-tag[i]; num+=lower_bound(b+(i-1)*m+1,b+i*m+1,cnt)-b-(i-1)*m-1;//少减一wa } for(int i=(pos[r]-1)*m+1;i<=r;i++){ if(a[i]+tag[pos[r]]<c) num++; } } return num; } int main() { scanf("%d",&n); for(int i=1;i<=n;i++){ scanf("%d",&a[i]); b[i]=a[i]; } m=sqrt(n); for(int i=1;i<=n;i++) pos[i]=(i-1)/m+1; for(int i=1;i<=m+1;i++){ sort(b+(i-1)*m+1,b+min(i*m,n)+1); } for(int i=1;i<=n;i++){ int op,l,r; ll c; scanf("%d%d%d%lld",&op,&l,&r,&c); if(op==0){ update(l,r,c); } else{ printf("%d\n",getnum(l,r,c*c)); } } return 0; } /* 5 1 3 7 2 5 0 1 3 1 1 1 3 2 1 1 4 1 1 2 3 2 1 3 5 4 1 0 0 3 */ /* 10 1 3 4 2 5 7 11 3 5 1 0 1 5 1 1 1 7 2 0 3 9 1 1 4 8 2 1 1 10 2 1 3 5 3 1 5 10 3 1 6 10 2 1 2 7 2 1 2 7 3 2 0 2 3 5 1 0 5 */