終於肝完了分塊的九種基礎類型,調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;
}