分块算法
题解:
分块好写好调好对拍。。
大部分的题目可以用其他数据结构来解决
但是对于一部分题目分块有自己的优势
下面这两道题目是只能用分块算法来做
教主的魔法
线段树套平衡树是可以维护这个东西的,但是这题预处理复杂度
分块+块内二分查找
注意二分查找的时候如果可能比h要小
这是个老问题了。。。
// luogu-judger-enable-o2 #include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) #define mid ((h+t)/2) #define me(x) memset(x,0,sizeof(x)) const int N=1e6+10; int n,q,block; int a[N],b[N],pos[N],lazy[N]; IL bool cmp(int x,int y) { return(x<y); } IL void reset(int x) { int h=(x-1)*block+1,t=min(x*block,n); rep(i,h,t) b[i]=a[i]; sort(b+h,b+t+1,cmp); } IL int find(int x,int v) { int h=(x-1)*block+1,t=min(x*block,n); int tmp=t; while (h<t) { if (b[mid]<v) h=mid+1; else t=mid; } if (tmp==t&&b[t]<v) t++; return(tmp-t+1); } IL void updata(int x,int y,int v) { if (pos[x]==pos[y]) { rep(i,x,y) a[i]+=v; } else { int l1=pos[x]*block; rep(i,x,l1) a[i]+=v; rep(i,(pos[y]-1)*block+1,y) a[i]+=v; } reset(pos[x]); reset(pos[y]); rep(i,pos[x]+1,pos[y]-1) lazy[i]+=v; } IL int query(int x,int y,int v) { int sum=0; if (pos[x]==pos[y]) { rep(i,x,y) if (a[i]+lazy[pos[i]]>=v) sum++; } else { int l1=pos[x]*block; rep(i,x,l1) if (a[i]+lazy[pos[i]]>=v) sum++; rep(i,(pos[y]-1)*block+1,y) if (a[i]+lazy[pos[i]]>=v) sum++; } rep(i,pos[x]+1,pos[y]-1) { sum+=find(i,v-lazy[i]); } return sum; } int main() { ios::sync_with_stdio(false); cin>>n>>q; block=sqrt(n); rep(i,1,n) cin>>a[i],pos[i]=(i-1)/block+1; int m=(n-1)/block+1; rep(i,1,m) reset(i); rep(i,1,q) { char ch[5]; int x,y,v; cin>>ch>>x>>y>>v; if(ch[0]=='M') updata(x,y,v); else cout<<query(x,y,v)<<endl; } return 0; }
6285. 数列分块入门 9
这道题尽显分块优势
首先有一个结论是a&b=a&b众数
这个很显然
然后就可以搞分块了
另外分块的时候要求查询x-y中为c的个数
这个也是可以分块的
这里非常巧妙做到O(1)查询
具体的可以看clj的论文
#include <bits/stdc++.h> using namespace std; #define rint register int #define IL inline #define rep(i,h,t) for (rint i=h;i<=t;i++) #define dep(i,t,h) for (rint i=t;i>=h;i--) const int N=1e5+100; const int N2=320; const int INF=1e9; int pos[N],pos2[N],b[N],c[N],d[N]; int f[N2][N],ph[N2],pt[N2],p[N2][N2]; int cnt[N2][N2][N2],now[N2][N]; int n,m,block; struct re{ int a,b; }a[N]; bool cmp(re x,re y) { return(x.a<y.a); } void reset1(int x) { int h=(x-1)*block+1,t=min(x*block,n); int cnt1=0; rep(i,h,t) c[i]=b[i]; sort(c+h,c+t+1); rep(i,h,t) { if (c[i]!=c[i-1]||(i==h)) ++cnt1; f[x][c[i]]=cnt1; } rep(i,1,t-h+1) { rep(j,1,t-h+1) cnt[x][i][j]=cnt[x][i-1][j]; cnt[x][i][f[x][b[i+h-1]]]++; } rep(i,h,t) now[x][b[i]]++; } IL int query2(int o,int x) { return now[pos[o]-1][x]+cnt[pos[o]][o-ph[pos[o]]+1][f[pos[o]][x]]; } #define query(h,t,x) query2(t,x)-query2(h-1,x) void reset(int x) { int h=(x-1)*block+1,t=min(x*block,n); ph[x]=h; pt[x]=t; int ans1=0,ans2=INF; rep(i,h,t) { int aa=query(h,t,b[i]); if (aa>ans1||(ans1==aa&&b[i]<ans2)) ans1=aa,ans2=b[i]; } p[x][x]=ans2; } int main() { freopen("1.in","r",stdin); freopen("1.out","w",stdout); ios::sync_with_stdio(false); cin>>n; rep(i,1,n) cin>>a[i].a,a[i].b=i; sort(a+1,a+n+1,cmp); a[0].a=INF; int cnt=0; rep(i,1,n) if(a[i].a!=a[i-1].a) b[a[i].b]=++cnt,pos2[cnt]=a[i].a; else b[a[i].b]=cnt; block=sqrt(n); rep(i,1,n) pos[i]=(i-1)/block+1; m=(n-1)/block+1; rep(i,1,m) reset1(i); rep(i,1,m) rep(j,1,n) now[i][j]+=now[i-1][j]; rep(i,1,m) reset(i); rep(i,1,m-1) rep(j,1,m-i) { int ans1=query(ph[j],pt[j+i],p[j][j+i-1]),ans2=p[j][j+i-1]; int h=ph[j+i],t=pt[j+i]; rep(k,h,t) { int kk=query(ph[j],pt[j+i],b[k]); if (kk>ans1||(ans1==kk&&b[k]<ans2)) ans1=kk,ans2=b[k]; } p[j][i+j]=ans2; } rep(i,1,n) { int x,y; cin>>x>>y; int ans1=0,ans2=INF; if (pos[x]==pos[y]) { rep(i,x,y) { int kk=query(x,y,b[i]); if (kk>ans1||(kk==ans1&&b[i]<ans2)) ans1=kk,ans2=b[i]; } } else { if (pos[x]+1<=pos[y]-1) ans2=p[pos[x]+1][pos[y]-1],ans1=query(x,y,ans2); else ans2=INF,ans1=0; int l1=pos[x]*block; rep(i,x,l1) { int kk=query(x,y,b[i]); if(kk>ans1||(kk==ans1&&b[i]<ans2)) ans1=kk,ans2=b[i]; } rep(i,(pos[y]-1)*block+1,y) { int kk=query(x,y,b[i]); if(kk>ans1||(kk==ans1&&b[i]<ans2)) ans1=kk,ans2=b[i]; } } cout<<pos2[ans2]<<endl; } return 0; }