#6277. 数列分块入门 1
样例输入
4
1 2 2 3
0 1 3 1
1 0 1 0
0 1 2 2
1 0 2 0
样例输出
2
5
n<5e4 , -2^31 <=others, ans<=2^31-1
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define m(a,b) memset(a,b,sizeof a)
#define sld(a) scanf("%lld",&a)
#define en '\n'
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f,N=5e4+5;
ll tag[230],a[N];
int bl[N],block;
void chanspan(int l,int r,int c)
{
for(int i=l;i<=min(bl[l]*block,r);i++)
a[i]+=c;
if(bl[l]!=bl[r])
for(int i=(bl[r]-1)*block+1;i<=r;i++)
a[i]+=c;
for(int i=bl[l]+1;i<=bl[r]-1;i++)
tag[i]+=c;
}
int main()
{
int n;scanf("%d",&n);block=sqrt(n);
for(int i=1;i<=n;i++)
scanf("%lld",&a[i]),bl[i]=(i-1)/block+1;
for(int i=1;i<=n;i++)
{
int f,l,r,c;scanf("%d%d%d%d",&f,&l,&r,&c);
if(!f)
chanspan(l,r,c);
else
printf("%lld\n",a[r]+tag[bl[r]]);
}
}
样例输入
4
1 2 2 3
0 1 3 1
1 1 3 2
1 1 4 1
1 2 3 2
样例输出
3
0
2
n<5e4 , -2^31 <=others, ans<=2^31-1
修改:
零散:将a[i]修改,将其所在块儿的vec[bl[l]],vec[bl[r]]修改。vec[i].push_back(a[i]),不是a[i]+tag[i],因为查询的时候,查询c-tag[i]。
整块:直接修改tag[i].(i是第几块)。
查询:
零散:遍历暴力查询, if(a[i]+tag[bl[l]]<c) if(a[i]+tag[bl[r]]<c) ++num;
整块:对该块的vec[i]二分lower_bound(c-tag[i])。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#include<vector>
#define m(a,b) memset(a,b,sizeof a)
#define en '\n'
using namespace std;
typedef long long ll;
const int INF=0x3f3f3f3f,N=5e4+5;
ll tag[230],a[N];
int bl[N],block,n;
vector<ll>vec[230];
void reset(int x)
{
vec[x].clear();
for(int i=(x-1)*block+1;i<=min(x*block,n);i++)
vec[x].push_back(a[i]);
sort(vec[x].begin(),vec[x].end());
}
void chanspan(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