链接:https://loj.ac/problem/6278
思路:
分块是真的好用。。。每个块排好序,两端的块直接暴力找就可以了,中间的块用二分找,每次更新重新对两边的块排序就好了。
实现代码:
#include<bits/stdc++.h> using namespace std; const int M = 1e5+10; vector<int>v[M]; int a[M],bl[M],block,tag[M],n,ans; void reset(int x){ v[x].clear(); for(int i = (x-1)*block+1;i <= min(n,x*block);i ++){ v[x].push_back(a[i]); } sort(v[x].begin(),v[x].end()); } void update(int l,int r,int c){ for(int i = l;i <= min(bl[l]*block,r);i ++){ a[i] += c; } reset(bl[l]); if(bl[l]!=bl[r]){ for(int i = (bl[r]-1)*block+1;i <= r;i ++) a[i]+=c; reset(bl[r]); } for(int i = bl[l]+1;i <= bl[r]-1;i ++) tag[i] += c; } int query(int l,int r,int c){ int ans = 0; for(int i = l;i <= min(bl[l]*block,r);i++) if(a[i]+tag[bl[l]] < c) ans++; if(bl[l]!=bl[r]){ for(int i = (bl[r]-1)*block+1;i <= r;i ++) if(a[i]+tag[bl[r]] < c) ans++; } for(int i = bl[l]+1;i <= bl[r]-1;i ++){ int x = c - tag[i]; ans += lower_bound(v[i].begin(),v[i].end(),x) - v[i].begin(); } return ans; } int main() { int f,l,r,c; cin>>n; block = sqrt(n); for(int i = 1;i <= n;i ++) cin>>a[i]; for(int i = 1;i <= n;i ++){ bl[i] = (i-1)/block + 1; v[bl[i]].push_back(a[i]); } for(int i = 1;i <= bl[n];i ++){ sort(v[i].begin(),v[i].end()); } for(int i = 1;i <= n;i ++){ cin>>f>>l>>r>>c; if(f == 0) update(l,r,c); else cout<<query(l,r,c*c)<<endl; } return 0; }