6277. 数列分块入门 1【区间修改 单点查询】
#include <bits/stdc++.h>
using namespace std;
const int N = 1e5 + 10;
typedef long long int LL;
LL a[N], ad[N], id[N], n, m, len;
//ad[i] 编号为i的块加的总数 id[i] i所对应的块
void add(int l, int r, int v)
{
for (int i = l; i <= min(r * 1ll, id[l]*len); i++) a[i] += v; //开头的不完整的
if (id[l] == id[r]) return;//在一个块里
for (int i = id[l] + 1; i <= id[r] - 1; i++) ad[i] += v;//中间完整的块
for (int i = (id[r] - 1) * len + 1; i <= r; i++) a[i] += v;//结束不完整的
}
LL query(int x) {
return a[x] + ad[id[x]];
}
int main(void) {
cin >> n ;
len = sqrt(n);
for (int i = 1; i <= n; i++) cin>>a[i];
for (int i = 1; i <= n; i++) id[i]=(i-1)/len+1;
for(int i = 1; i <= n; i++)
{
int op, l, r, c;
cin >> op >> l >> r >> c;
if (op == 0) add(l, r, c);
else cout << query(r) << endl;
}
return 0;
}
6278. 数列分块入门 2【区间加 区间查询小于x的个数】
对于每一个块二分,可以快速的求出一个块内小于x的个数。
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
typedef long long int LL;
LL a[N],ad[N],id[N],n,len;
vector<LL>ve[N];
void solve(int x)
{
ve[x].clear();
for(int i=(x-1)*len+1;i<=min(x*len,n);i++) ve[x].push_back(a[i]);
sort(ve[x].begin(),ve[x].end());
}
void add(LL l,LL r,LL c)
{
for(int i=l;i<=min(r,id[l]*len);i++) a[i]+=c;
solve(id[l]);
if(id[l]==id[r]) return;
for(int i=id[l]+1;i<=id[r]-1;i++) ad[i]+=c;
for(int i=(id[r]-1)*len+1;i<=r;i++) a[i]+=c;
solve(id[r]);
}
LL query(LL l,LL r,LL x)
{
int ans=0;
for(int i=l;i<=min(r,id[l]*len);i++) if(a[i]+ad[id[i]]<x) ans++;
if(id[l]==id[r]) return ans;
for(int i=id[l]+1;i<=id[r]-1;i++)
{
int c=x-ad[i];
ans+=lower_bound(ve[i].begin(),ve[i].end(),c)-ve[i].begin();
}
for(int i=(id[r]-1)*len+1;i<=r;i++) if(a[i]+ad[id[i]]<x) ans++;
return ans;
}
int main(void)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
len=sqrt(n);
for(int i=1;i<=n;i++)
{
id[i]=(i-1)/len+1;
ve[id[i]].push_back(a[i]);
}
for(int i=1;i<=id[n];i++) sort(ve[i].begin(),ve[i].end());
for(int i=0;i<n;i++)
{
int op,l,r,c; cin>>op>>l>>r>>c;
if(!op) add(l,r,c);
else cout<<query(l,r,c*c)<<endl;
}
return 0;
}
6279. 数列分块入门 3【区间修改 区间查询小于x的最大值】
#include<bits/stdc++.h>
using namespace std;
const int N=1e5*5+10;
typedef long long int LL;
LL a[N],ad[N],id[N],n,len;
vector<LL>ve[N];
void solve(int x)
{
ve[x].clear();
for(int i=(x-1)*len+1;i<=min(x*len,n);i++) ve[x].push_back(a[i]);
sort(ve[x].begin(),ve[x].end());
}
void add(LL l,LL r,LL c)
{
for(int i=l;i<=min(r,id[l]*len);i++) a[i]+=c;
solve(id[l]);
if(id[l]==id[r]) return;
for(int i=id[l]+1;i<=id[r]-1;i++) ad[i]+=c;
for(int i=(id[r]-1)*len+1;i<=r;i++) a[i]+=c;
solve(id[r]);
}
LL query(LL l,LL r,LL x)
{
LL ans=-1e18;
for(int i=l;i<=min(r,id[l]*len);i++)
if(a[i]+ad[id[i]]<x) ans=max(ans,a[i]+ad[id[i]]);
if(id[l]==id[r])
{
if(ans==-1e18) return -1;
return ans;
}
for(int i=id[l]+1;i<=id[r]-1;i++)
{
LL c=x-ad[i];
int index=lower_bound(ve[i].begin(),ve[i].end(),c)-ve[i].begin();
index--;
if(index>=0) ans=max(ans,ve[i][index]+ad[i]);
}
for(int i=(id[r]-1)*len+1;i<=r;i++) if(a[i]+ad[id[i]]<x) ans=max(ans,a[i]+ad[id[i]]);
if(ans==-1e18) return -1;
return ans;
}
int main(void)
{
cin>>n;
for(int i=1;i<=n;i++) cin>>a[i];
len=sqrt(n);
for(int i=1;i<=n;i++)
{
id[i]=(i-1)/len+1;
ve[id[i]].push_back(a[i]);
}
for(int i=1;i<=id[n];i++) sort(ve[i].begin(),ve[i].end());
for(int i=0;i<n;i++)
{
int op,l,r,c; cin>>op>>l>>r>>c;
if(!op) add(l,r,c);
else cout<<query(l,r,c)<<endl;
}
return 0;
}