终于肝完了分块的九种基础类型,调bug调得是真(超)是(级)开(恶)心。
有脑残的时候,把块的编号当成元素的下表。数组开太小会莫名超时。
建议读者刷LOJ上的分块入门1~9
loj#6277. 数列分块入门 1
区间加法,单点查询
基础的东西
数学老师曰:基本知识不熟悉,难题不会做!
分块 每个块的大小都是sqrt(n)
n=12 N=sqrt(12) 向下取整 3
第一块:1~3 第二块:4~6 第三块:7~9 第四块: 10~12
属于第几块pos[i]=(i-1)/N+1;
如果是完整的块就直接更新到标记里
不完整的块就直接暴力更新就ok
loj#6278. 数列分块入门 2
区间加法,查询比x小的个数
排序维护一下块内的递增性
完整的块可以直接用lower_bound返回一下第一个大于等于x的位置
不完整的块还是直接暴力
loj#6279. 数列分块入门 3
区间加法,求某个数的前驱
用vector维护方便很多
依旧是完整的块直接lower_bound
不完整的块还是继续暴力
loj#6280. 数列分块入门 4
区间加法,区间求和
和分块1是差不多的
顺着思路用多一个数组来记录每一个块的总和就可以
loj#6281. 数列分块入门 5
区间开方,区间求和
其实不难发现就,即使是开方,操作量也不是很大
就拿最大值 2^31来说 开5次平方就已经小于2接近1了
所以当一个数已经小于等于1的时候 开方也没有什么意义了(向下取整不是0就是1 1^n=1 0^n=0)
同理,我们参照上面的思路开多一个数组标记这个块内的数是不是全都小于等于1了,是的话直接不用更新就ok
loj#6282. 数列分块入门 6//需要写
单点插入,单点询问
用vector存储每一个块的元素
当其中某一个块插入的元素过多的时候,那么我们重新构造一下。
loj#6283. 数列分块入门 7
区间乘法,区间加法,区间查询
其实和第二题并没有什么本质区别……
维护一个加法标记再维护一个乘法标记就ok
但是注意维护两个标记的时候要麻烦一点
其实记住运用好小学知识——乘法分配率 就ok
taga(加法标记)tagc(乘法标记)
先加再乘:taga=taga*c——tagc*=c
先乘再加:taga+=c ——tagc=tagc
暴力更新不完整的块的时候要先把之前整个块的两个标记放下去,再进行这一次的操作
还有记得初始化乘法标记不要写0……
loj#6284. 数列分块入门 8
区间询问,区间修改
继续运用上面的思路用上各种各样的标记就凹k
用一个数组记录这一个块内是否都是同一个数
是的话标记为这个数,否则为-1
查询的时候分情况讨论标记是否为-1 、c、≠c&&≠ -1
-1直接暴力for一遍统计然后更新标记
≠ -1&&≠c 没得询问直接更新
==c ans+=N 不用询问直接更新答案就好
loj#6285. 数列分块入门 9
查询区间最小众数
害怕太大所以离散化重新强制遍了一个号
然后利用map表每个元素只能出现一次的特质来存一下每个数离散化后的编号
顺便用一波vector统计一下每个数第一个出现的位置
然后dp一波把每一个完整块内的众数先预处理一下
然后还是像上面那样
不完整的块暴力查找
完整的块直接max一下就好啦
代码:
LOJ 6277
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
using namespace std;
const int maxn=5e4+10;
int n,m,l[maxn],r[maxn],be[maxn],p[maxn],a[maxn],num,block;
void build(){
int i;
block=sqrt(n);
num=n/block;
if(n%block) num++;
for(i=1;i<=n;i++){
be[i]=(i-1)/block+1;
}
for(i=1;i<=num;i++){
l[i]=(i-1)*block+1;
r[i]=i*block;p[i]=0;
}
r[num]=n;
}
void chage(int L,int R,int val){
int i;
if(be[L]==be[R]){
for(i=L;i<=R;i++){
a[i]+=val;
}
return ;
}
for(i=L;i<=r[be[L]];i++) a[i]+=val;
for(i=R;i>=l[be[R]];i--) a[i]+=val;
for(i=be[L]+1;i<be[R];i++)
p[i]+=val;
}
int main(){
int i,j;
while(scanf("%d",&n)!=EOF){
for(i=1;i<=n;i++) scanf("%d",&a[i]);
build();
int ki,L,R,w;
for(i=0;i<n;i++){
scanf("%d%d%d%d",&ki,&L,&R,&w);
if(ki==0){
chage(L,R,w);
}
else{
printf("%d\n",a[R]+p[be[R]]);
}
}
}
return 0;
}
LOJ6278
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=5e4+10;
int n,m,num,block,a[maxn],p[505],be[maxn];
vector<int> G[505];
void reset(int x){
G[x].clear();
for(int i=(x-1)*block+1;i<=min(n,x*block);i++) G[x].push_back(a[i]);
sort(G[x].begin(),G[x].end());
}
void build(){
mem(p,0);
int i;
for(i=1;i<=n/block+1;i++) G[i].clear();
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
be[i]=(i-1)/block+1;
G[be[i]].push_back(a[i]);
}
for(i=1;i<=be[n];i++){
sort(G[i].begin(),G[i].end());
}
}
void cha(int L,int R,int val){
int i;
for(i=L;i<=min(be[L]*block,R);i++) a[i]+=val;
reset(be[L]);
if(be[L]!=be[R]){
for(i=(be[R]-1)*block+1;i<=R;i++) a[i]+=val;
reset(be[R]);
}
for(i=be[L]+1;i<be[R];i++)
p[i]+=val;
}
int ans;
void query(int L,int R,int val){
int i;
for(i=L;i<=min(R,be[L]*block);i++){
if(a[i]+p[be[L]]<val) ans++;
}
if(be[L]!=be[R]){
for(i=(be[R]-1)*block+1;i<=R;i++){
if(a[i]+p[be[R]]<val) ans++;
}
}
for(i=be[L]+1;i<be[R];i++){
int x=val-p[i];
ans+=lower_bound(G[i].begin(),G[i].end(),x)-G[i].begin();
}
printf("%d\n",ans);
}
int main(){
int i,j;
while(scanf("%d",&n)!=EOF){
block=sqrt(n);
build();
ll ki,u,v,w;
for(i=0;i<n;i++){
scanf("%d%d%d%d",&ki,&u,&v,&w);
if(ki==0){
cha(u,v,w);
}
else{
ans=0;
query(u,v,w*w);
}
}
}
return 0;
}
LOJ6279
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
using namespace std;
const int maxn=1e5+10;
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
int n,m,block,a[maxn],p[550],be[maxn];
vector<int> G[550];
void reset(int x){
G[x].clear();
for(int i=(x-1)*block+1;i<=min(n,x*block);i++) G[x].push_back(a[i]);
sort(G[x].begin(),G[x].end());
}
void build(){
int i;
block=sqrt(n);
for(i=1;i<=n/block+1;i++) G[i].clear();
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
be[i]=(i-1)/block+1;
G[be[i]].push_back(a[i]);
}
mem(p,0);
for(i=1;i<=be[n];i++){
sort(G[i].begin(),G[i].end());
}
}
void cha(int l,int r,int val){
int i;
for(i=l;i<=min(be[l]*block,r);i++) a[i]+=val;
reset(be[l]);
if(be[l]!=be[r]){
for(i=(be[r]-1)*block+1;i<=r;i++) a[i]+=val;
reset(be[r]);
}
for(i=be[l]+1;i<be[r];i++){
p[i]+=val;
}
}
int ask(int pos,int val){
int l=0,r=G[pos].size()-1,ans=0;
if(G[pos][0]+p[pos]>=val) return -0x3f3f3f;
while(l<=r)
{
int mid=(l+r)>>1;
if(G[pos][mid]+p[pos]<val) ans=mid,l=mid+1;
else r=mid-1;
}
return G[pos][ans]+p[pos];
}
int ans=0;
void query(int l,int r,int val){
int i;
for(i=l;i<=min(be[l]*block,r);i++){
if(a[i]+p[be[i]]<val) ans=max(ans,a[i]+p[be[i]]);
}
if(be[r]!=be[l]){
for(i=(be[r]-1)*block+1;i<=r;i++){
if(a[i]+p[be[i]]<val) ans=max(ans,a[i]+p[be[i]]);
}
}
for(i=be[l]+1;i<be[r];i++){
ans=max(ans,ask(i,val));
}
if(ans!=-0x3f3f3f)
printf("%d\n",ans);
else puts("-1");
}
int main(){
int i,j;
while(scanf("%d",&n)!=EOF){
build();
int ki,u,v,w;
for(i=1;i<=n;i++){
scanf("%d%d%d%d",&ki,&u,&v,&w);
if(ki==0){
cha(u,v,w);
}
else{
ans=-0x3f3f3f;
query(u,v,w);
}
}
}
return 0;
}
LOJ6280
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
using namespace std;
const int maxn=5e4+10;
#define min(a,b) ((a)>(b)?b:a)
#define ll long long
#define mem(a,b) memset(a,b,sizeof(a))
int n,m,num,block;
ll a[maxn],p[550],be[maxn],d[550];
inline void build(){
int i;
block=sqrt(n);
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
be[i]=(i-1)/block+1;
d[be[i]]+=a[i];
}
}
inline void cha(int l,int r,int val){
int i;
for(i=l;i<=min(r,be[l]*block);i++) a[i]+=val,d[be[i]]+=val;
if(be[l]^be[r]){
for(i=(be[r]-1)*block+1;i<=r;i++) a[i]+=val,d[be[i]]+=val;
}
for(i=be[l]+1;i<be[r];i++) p[i]+=val;
}
ll ans;
void query(int l,int r,int val){
int i;
for(i=l;i<=min(r,be[l]*block);i++){
ans+=(a[i]+p[be[i]]);
ans%=val;
}
if(be[r]^be[l]){
for(i=(be[r]-1)*block+1;i<=r;i++){
ans+=a[i]+p[be[i]];
ans%=val;
}
}
for(i=be[l]+1;i<be[r];i++){
ans+=(d[i]+1LL*p[i]*block)%val;
ans%=val;
}
printf("%lld\n",ans%val);
}
int main(){
int i,j;
scanf("%d",&n);
build();
int ki,u,v,w;
for(i=0;i<n;i++){
scanf("%d%d%d%d",&ki,&u,&v,&w);
if(ki==0) cha(u,v,w);
else{
ans=0;
query(u,v,w+1);
}
}
return 0;
}
LOJ6281
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
using namespace std;
const int maxn=5e4+10;
#define ll long long
#define min(a,b) (a>b?b:a)
int n,m,block;
int a[maxn],p[550],be[maxn],d[550];
bool vis[550];
void reset(int x){
int i,flag=1;
if(vis[x]) return ;
vis[x]=1;
for(i=(x-1)*block+1;i<=x*block;i++){
d[x]-=a[i];
a[i]=sqrt(a[i]);
d[x]+=a[i];
if(a[i]>1){
vis[x]=0;
}
}
}
void build(){
int i;
block=sqrt(n);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
be[i]=(i-1)/block+1;
d[be[i]]+=a[i];
}
for(i=be[1];i<=be[n];i++) vis[i]=false;
}
void add(int l,int r){
int i;
if(!vis[be[l]]){
for(i=l;i<=min(be[l]*block,r);i++){
d[be[i]]-=a[i];
a[i]=sqrt(a[i]);
d[be[i]]+=a[i];
}
vis[be[l]]=1;
for(i=(be[l]-1)*block+1;i<=be[l]*block;i++){
if(a[i]>1){
vis[be[i]]=false;break;
}
}
}
if(be[l]^be[r]&&!vis[be[r]]){
for(i=(be[r]-1)*block+1;i<=r;i++){
d[be[i]]-=a[i];
a[i]=sqrt(a[i]);
d[be[i]]+=a[i];
}
vis[be[r]]=1;
for(i=(be[r]-1)*block+1;i<=min(be[r]*block,n);i++){
if(a[i]>1){
vis[be[i]]=false;break;
}
}
}
for(i=be[l]+1;i<be[r];i++){
reset(i);
}
}
int ans;
void query(int l,int r){
int i;
for(i=l;i<=min(r,be[l]*block);i++){
ans+=a[i];
}
if(be[l]^be[r]){
for(i=(be[r]-1)*block+1;i<=r;i++){
ans+=a[i];
}
}
for(i=be[l]+1;i<be[r];i++){
ans+=d[i];
}
printf("%d\n",ans);
}
int main(){
int i,j;
scanf("%d",&n);
build();
int ki,u,v,w;
for(i=1;i<=n;i++){
scanf("%d%d%d%d",&ki,&u,&v,&w);
if(!ki) add(u,v);
else{
ans=0;
query(u,v);
}
}
return 0;
}
LOJ6282
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<math.h>
#define mem(a,b) memset(a,b,sizeof(a))
using namespace std;
const int maxn=2e5+100;
const int mm=sqrt(maxn)+10;
int n,m,be[maxn],a[maxn<<1],num,block;
vector<int> ve[mm];
void rebuild(){
int cur=1,i,j;
for(i=1;i<=num;i++){
int len=ve[i].size();
for(j=0;j<len;j++){
a[cur++]=ve[i][j];
}
ve[i].clear();
}
cur--;
block=2*sqrt(cur);
num=cur/block;
if(cur%block) num++;
for(i=1;i<=cur;i++){
be[i]=(i-1)/block+1;
ve[be[i]].push_back(a[i]);
}
}
int main(){
int i,j,tmp;
scanf("%d",&n);
block=2*sqrt(n);
num=n/block;
if(n%block) num++;
for(i=1;i<=n;i++){
be[i]=(i-1)/block+1;
scanf("%d",&tmp);
ve[be[i]].push_back(tmp);
}
int ki,l,r,w;
for(i=0;i<n;i++){
scanf("%d%d%d%d",&ki,&l,&r,&w);
if(!ki){
int g=0,pos=0;
for(j=1;j<=num;j++){
int len=(int)ve[j].size();
if(l-len>0) l-=len;
else{
g=j;pos=l;break;
}
}
ve[g].insert(ve[g].begin()+pos-1,r);
if(ve[g].size()>7*block) rebuild();
}
else{
int g=0,pos=0;
for(j=1;j<=num;j++){
int len=(int)ve[j].size();
if(r-len>0) r-=len;
else{
g=j,pos=r;
break;
}
}
printf("%d\n",ve[g][pos-1]);
}
}
return 0;
}
LOJ6283
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
const int maxn=1e5+10;
const int mm=sqrt(maxn)+10;
const long long mod=10007;
#define ll long long
int n,m,num,block,be[maxn];
ll a[maxn],p[550],mul[550];
void build(){
int i,j;
block=sqrt(n);
num=n/block;
if(n%block) num++;
for(i=1;i<=n;i++){
scanf("%lld",&a[i]);
be[i]=(i-1)/block+1;
}
for(i=1;i<=num;i++) p[i]=0,mul[i]=1;
}
void cha(int l,int r,int val){//+
int i;
for(i=(be[l]-1)*block+1;i<=min(be[l]*block,n);i++){
a[i]=(a[i]*mul[be[l]]+p[be[l]]+mod)%mod;
if(i>=l&&i<=r) a[i]+=val+mod,a[i]%=mod;
}
mul[be[l]]=1;p[be[l]]=0;
if(be[l]^be[r]){
for(i=(be[r]-1)*block+1;i<=min(be[r]*block,n);i++){
a[i]=(a[i]*mul[be[r]]%mod+p[be[r]]+mod)%mod;
if(i>=l&&i<=r) a[i]+=val+mod,a[i]%=mod;
}
mul[be[r]]=1;p[be[r]]=0;
}
for(i=be[l]+1;i<be[r];i++){
p[i]=(p[i]+val+mod)%mod;
}
}
void add(int l,int r,int val){//*
int i;
for(i=(be[l]-1)*block+1;i<=be[l]*block;i++){
a[i]=(a[i]*mul[be[l]]%mod+p[be[l]]+mod)%mod;
if(i>=l&&i<=r) a[i]*=val,a[i]%=mod,a[i]=(a[i]+mod)%mod;
}
mul[be[l]]=1;p[be[l]]=0;
if(be[l]^be[r]){
for(i=(be[r]-1)*block+1;i<=min(be[r]*block,n);i++){
a[i]=(a[i]*mul[be[r]]%mod+p[be[r]]+mod)%mod;
if(i>=l&&i<=r) a[i]*=val,a[i]%=mod,a[i]=(a[i]+mod)%mod;
}
mul[be[r]]=1;p[be[r]]=0;
}
for(i=be[l]+1;i<be[r];i++){
mul[i]=(mul[i]*val+mod)%mod;
p[i]=(p[i]*val+mod)%mod;
}
}
int main(){
int i,j;
scanf("%d",&n);
build();
int ki,l,r,w;
for(i=0;i<n;i++){
scanf("%d%d%d%d",&ki,&l,&r,&w);
if(ki==0){
cha(l,r,w);
}
else if(ki==1){
add(l,r,w);
}
else{
printf("%lld\n",(a[r]*mul[be[r]]+p[be[r]])%mod);
}
}
return 0;
}
LOJ6284
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<math.h>
#include<vector>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=1e5+1000;
const int mm=sqrt(maxn)+10;
int n,m,a[maxn],be[maxn],num,block,flag;
int vis[mm];
void build(){
int i;
block=sqrt(n);
num=n/block;
if(n/block) num++;
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
be[i]=(i-1)/block+1;
}
mem(vis,-1);
}
void query(int l,int r,int val){
int i,ans=0,j;
if(be[l]==be[r]){
if(vis[be[l]]==val) ans+=r-l+1;
else{
if(vis[be[l]]!=-1){
for(i=(be[l]-1)*block+1;i<=be[l]*block;i++) a[i]=vis[be[l]];
}
for(i=l;i<=r;i++) if(a[i]==val) ans++;else a[i]=val;
vis[be[l]]=val;
for(i=(be[l]-1)*block+1;i<=min(be[l]*block,n);i++)if(a[i]!=val){ vis[be[l]]=-1;break;}
}
}
else{
if(vis[be[l]]==val) ans+=(be[l]*block-l+1);
else{
if(vis[be[l]]!=-1)
for(i=(be[l]-1)*block+1;i<=be[l]*block;i++) a[i]=vis[be[l]];
for(i=l;i<=be[l]*block;i++) if(a[i]==val) ans++;else a[i]=val;
vis[be[l]]=val;
for(i=(be[l]-1)*block+1;i<=be[l]*block;i++) if(a[i]!=val){vis[be[l]]=-1;break;}
}
if(vis[be[r]]==val) ans+=r-((be[r]-1)*block);
else{
if(vis[be[r]]!=-1)
for(i=(be[r]-1)*block+1;i<=be[r]*block;i++) a[i]=vis[be[r]];
for(i=(be[r]-1)*block+1;i<=r;i++) if(a[i]==val) ans++;else a[i]=val;
vis[be[r]]=val;
for(i=(be[r]-1)*block+1;i<=min(be[r]*block,n);i++) if(a[i]!=val){vis[be[r]]=-1;break;}
}
for(i=be[l]+1;i<be[r];i++){
if(vis[i]==val) ans+=block;
else{
if(vis[i]!=-1) vis[i]=val;
else{
for(j=(i-1)*block+1;j<=i*block;j++) if(a[j]==val) ans++;else a[j]=val;
vis[i]=val;
for(j=(i-1)*block+1;j<=i*block;j++) if(a[j]!=val){vis[i]=-1;break;}
}
}
}
}
printf("%d\n",ans);
}
void solve(){
int i,j,ki,u,v,w;
for(i=1;i<=n;i++){
scanf("%d%d%d",&u,&v,&w);
query(u,v,w);
}
}
int main(){
int i,j;
scanf("%d",&n);
build();
solve();
return 0;
}
LOJ6285
#include<stdio.h>
#include<string.h>
#include<algorithm>
#include<vector>
#include<map>
#include<math.h>
using namespace std;
#define mem(a,b) memset(a,b,sizeof(a))
const int maxn=1e5+10000;
int n,be[maxn],v[maxn],cnt[maxn],a[maxn],id,num,block,f[550][550];
map<int,int> m;
vector<int> b[51000];
void dp(int x){
int i,maxx=0,ss=0;
mem(cnt,0);
for(i=(x-1)*block+1;i<=n;i++){
int cc=++cnt[a[i]];
if(cc>ss||cc==ss&&v[a[i]]<v[maxx]){
ss=cc;maxx=a[i];
}
f[x][be[i]]=maxx;
}
}
int along(int l,int r,int x){
int ans=upper_bound(b[x].begin(),b[x].end(),r)-lower_bound(b[x].begin(),b[x].end(),l);
return ans;
}
int slove(int x,int y){
int ss=0,maxx=0;
maxx=f[be[x]+1][be[y]-1];
ss=along(x,y,maxx);
for(int i=x;i<=min(be[x]*block,y);i++){
int cc=along(x,y,a[i]);
if(cc>ss||cc==ss&&v[a[i]]<v[maxx]){
ss=cc;
maxx=a[i];
}
}
if(be[x]^be[y]){
for(int i=(be[y]-1)*block+1;i<=y;i++){
int cc=along(x,y,a[i]);
if(cc>ss||cc==ss&&v[a[i]]<v[maxx]){
ss=cc;
maxx=a[i];
}
}
}
return maxx;
}
int main(){
int i,j;
scanf("%d",&n);
block=sqrt(n);
for(i=1;i<=n;i++){
scanf("%d",&a[i]);
be[i]=(i-1)/block+1;
if(m[a[i]]==0){
m[a[i]]=++id;
v[id]=a[i];
}
a[i]=m[a[i]];
b[a[i]].push_back(i);
}
for(i=1;i<=be[n];i++) dp(i);
for(i=1;i<=n;i++){
int x,y;
scanf("%d%d",&x,&y);
if(x>y) swap(x,y);
printf("%d\n",v[slove(x,y)]);
}
return 0;
}