分块入门 1
给出一个长为n的数列,以及n个操作,操作涉及区间加法,单点查值。
没啥说的直接上程序
#include <bits/stdc++.h>
#define rep(x, y, z) for(register int x = y; x <= z; x ++)
inline int read(){
char ch = getchar(); int u = 0, f = 1;
while (!isdigit(ch)){ if (ch == '-') f = -1; ch = getchar();}
while (isdigit(ch)) {u = (u << 3) + (u << 1) + ch - 48; ch = getchar();}
return u * f;
}
const int maxn = 500500;
int n, m, blo;
int v[maxn], tag[maxn], bl[maxn];
namespace Blo{//分块
inline void Add(int l, int r, int c){
rep (i, l, std::min(bl[l] * blo, r))
v[i] += c;
if (bl[l] != bl[r])
rep (i, (bl[r] - 1) * blo + 1, r)
v[i] += c;
rep (i, bl[l] + 1, bl[r] - 1)
tag[i] += c;
}
inline int query(int pos){//查询的时候就返回单点+块的标记
return v[pos] + tag[bl[pos]];
}
}
int main(){
n = read(), m = read(); blo = sqrt(n);//块的大小
for (int i = 1; i <= n; i++) bl[i] = (i - 1)/blo + 1;
for (int i = 1; i <= n; i++) v[i] = read();
while (m--){
int opt = read();
if (opt == 1) {int l = read(), r = read(), c = read(); Blo::Add(l, r, c);}
else {
int x = read();
printf("%d\n",Blo::query(x));
}
}
return 0;
}
分块入门 2
给出一个长为n的数列,以及n个操作,操作涉及区间加法,询问区间内小于某个值x的元素个数。
每个块内用vector维护排序,注意细节的处理
#include<iostream>
#include<algorithm>
#include<cstdio>
#include<cmath>
#include<vector>
#define int long long
using namespace std;
int n,t,a,b,c,opt;
int L[501],R[501],post[50010],val[50010],mark[501];
vector<int>linker[510];
void add(int a,int b,int c)
{
int p=post[a],q=post[b];
if(p==q)
{
linker[p].clear();
for(int i=a;i<=b;i++)
val[i]+=c;
for(int i=L[p];i<=R[p];i++)
linker[p].push_back(val[i]);
sort(linker[p].begin(),linker[p].end());
return;
}
else
{
for(int i=p+1;i<=q-1;i++)
mark[i]+=c;
linker[p].clear();
linker[q].clear();
for(int i=a;i<=R[p];i++)
val[i]+=c;
for(int i=L[q];i<=b;i++)
val[i]+=c;
for(int i=L[p];i<=R[p];i++)
linker[p].push_back(val[i]);
for(int i=L[q];i<=R[q];i++)
linker[q].push_back(val[i]);
sort(linker[p].begin(),linker[p].end());
sort(linker[q].begin(),linker[q].end());
return;
}
}
int query(int a,int b,int c)
{
int ans=0;
int p=post[a],q=post[b];
if(p==q)
{
for(int i=a;i<=b;i++)
if(val[i]+mark[p]<c)
ans++;
}
else
{
for(int i=a;i<=R[p];i++)
if(val[i]+mark[p]<c)
ans++;
for(int i=L[q];i<=b;i++)
if(val[i]+mark[q]<c)
ans++;
for(int i=p+1;i<=q-1;i++)
{
int x=c-mark[i];
ans+=lower_bound(linker[i].begin(),linker[i].end(),x)-linker[i].begin();
}
}
return ans;
}
main()
{
scanf("%lld",&n);
int t=sqrt(n);
for(int i=1;i<=n;i++)
scanf("%lld",&val[i]);
for(int i=1;i<=t;i++)
{
L[i]=(i-1)*t+1;
R[i]=i*t;
}
if(R[t]<n)
{
t++;
L[t]=R[t-1]+1;
R[t]=n;
}
for(int i=1;i<=t;i++)
{
for(int j=L[i];j<=R[i];j++)
{
post[j]=i;
linker[i].push_back(val[j]);
}
sort(linker[i].begin(),linker[i].end());
}
for(int i=1;i<=n;i++)
{
scanf("%lld%lld%lld%lld",&opt,&a,&b,&c);
if(opt==0)
add(a,b,c);
else
printf("%lld\n",query(a,b,c*c));
}
return 0;
}
程序