【习题整理】分块+莫队(未完待续)
注意:这是一篇十分劣质的博客,只有题目和简单的几句话,慎用。。。。。。。。。。OVO
分块
入门推荐:http://hzwer.com/8053.html
bzoj2957
这个题有线段树和分块两种做法;
线段树维护了区间的答案合并的时候维护高度最大值,右区的左子区间进一步讨论对分类讨论;
分块就对每个块维护一个可看到的上升序列,lower_bound即可;
1 #include<bits/stdc++.h> 2 #define ll long long 3 #define il inline 4 #define rg register 5 using namespace std; 6 const int N=100010,M=610; 7 int n,m,bl[N],u,t[M],len; 8 double a[N],g[M][M]; 9 il int find(int i,double x){ 10 int l=1,r=t[i]+1; 11 while(l<r){ 12 int mid=(l+r)>>1; 13 if(x<g[i][mid])r=mid; 14 else l=mid+1; 15 } 16 return l; 17 } 18 il void update(int x){ 19 int l=(bl[x]-1)*u+1,r=bl[x]*u; 20 t[bl[x]]=0; 21 for(rg int i=l;i<=r;i++) 22 if(g[bl[x]][t[bl[x]]]<a[i])g[bl[x]][++t[bl[x]]]=a[i]; 23 double mx=0; int ans=0; 24 for(rg int i=1;i<=len;i++){ 25 int p = find(i,mx); 26 ans += t[i]-p+1; 27 if(mx<g[i][t[i]])mx=g[i][t[i]]; 28 } 29 printf("%d\n",ans); 30 } 31 il char gc(){ 32 static char *p1,*p2,s[1000000]; 33 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 34 return(p1==p2)?EOF:*p1++; 35 } 36 il int rd(){ 37 int x=0; char c=gc(); 38 while(c<'0'||c>'9')c=gc(); 39 while(c>='0'&&c<='9')x=(x<<1)+(x<<3)+c-'0',c=gc(); 40 return x; 41 } 42 int main(){ 43 // freopen("bzoj2957.in","r",stdin); 44 // freopen("bzoj2957.out","w",stdout); 45 n=rd(); m=rd(); 46 u=550; 47 for(rg int i=1;i<=n;i++)bl[i]=(i-1)/u+1; 48 len=bl[n]; 49 for(rg int i=1;i<=n;i++)a[i]=-1; 50 for(rg int i=1,x,y;i<=m;i++){ 51 x=rd(),y=rd(); 52 a[x]=1.0*y/x; 53 update(x); 54 } 55 return 0; 56 }
bzoj2141
交换两个位置,维护逆序对;
考虑两个位置的影响,对每个块维护一个树状数组;
1 #include<bits/stdc++.h> 2 #define rg register 3 #define il inline 4 #define ll long long 5 using namespace std; 6 const int N=20010,M=810; 7 int n,m,c[M][N],a[N],sub[N],tot,sz[N],bl[N],u,len; 8 ll ans; 9 il char gc(){ 10 static char*p1,*p2,s[1000000]; 11 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 12 return(p1==p2)?EOF:*p1++; 13 } 14 il int rd(){ 15 int x=0; char C=gc(); 16 while(C<'0'||C>'9')C=gc(); 17 while(C>='0'&&C<='9')x=(x<<1)+(x<<3)+C-'0',C=gc(); 18 return x; 19 } 20 il void add(int id,int x,int y){for(rg int i=x;i<=tot;i+=i&-i)c[id][i]+=y;} 21 il int query(int id,int x){int re=0;for(rg int i=x;i;i-=i&-i)re+=c[id][i];return re;} 22 void update(int x,int y){ 23 int tx=a[x],ty=a[y]; 24 add(bl[x],a[x],-1); 25 add(bl[y],a[y],-1); 26 swap(a[x],a[y]); 27 add(bl[x],a[x],1); 28 add(bl[y],a[y],1); 29 if(tx>ty)ans--;else if(tx<ty)ans++; else return; 30 if((++x)>(--y))return ; 31 if(bl[x]==bl[y]){ 32 for(rg int i=x;i<=y;i++){ 33 if(tx<a[i])ans++;else if(tx>a[i])ans--; 34 if(ty>a[i])ans++;else if(ty<a[i])ans--; 35 } 36 }else{ 37 int t=bl[x]*u;for(rg int i=x;i<=t;i++){ 38 if(tx<a[i])ans++;else if(tx>a[i])ans--; 39 if(ty>a[i])ans++;else if(ty<a[i])ans--; 40 } 41 t=(bl[y]-1)*u+1;for(rg int i=t;i<=y;i++){ 42 if(tx<a[i])ans++;else if(tx>a[i])ans--; 43 if(ty>a[i])ans++;else if(ty<a[i])ans--; 44 } 45 for(rg int i=bl[x]+1;i<bl[y];i++){ 46 ans -= query(i,tx-1); 47 ans += sz[i] - query(i,tx); 48 ans -= sz[i] - query(i,ty); 49 ans += query(i,ty-1); 50 } 51 } 52 } 53 int main(){ 54 // freopen("bzoj2141.in","r",stdin); 55 // freopen("bzoj2141.out","w",stdout); 56 n=rd(); 57 for(rg int i=1;i<=n;i++)a[i]=sub[i]=rd(); 58 sort(sub+1,sub+n+1); 59 tot=unique(sub+1,sub+n+1)-sub-1; 60 u=pow(n,0.6666666)/*sqrt(n)*/ , len=(n-1)/u+1; 61 for(rg int i=n;i;i--){ 62 a[i]=lower_bound(sub+1,sub+tot+1,a[i])-sub; 63 bl[i]=(i-1)/u+1; 64 if(bl[i]==bl[i-1])sz[i]=sz[i-1]+1;else sz[i]=1; 65 add(bl[i],a[i],1); 66 ans += query(0,a[i]-1); 67 add(0,a[i],1); 68 } 69 printf("%lld\n",ans); 70 m=rd(); 71 for(rg int i=1;i<=m;i++){ 72 int x=rd(),y=rd(); 73 if(x>y)swap(x,y); 74 update(x,y); 75 printf("%lld\n",ans); 76 } 77 return 0; 78 }
bzoj3744
其实也一样,只不过多个套路维护每个块的前缀和就可以快速查询整块了(我没码。。。。。)
bzoj2821
也是套路,维护d[i][j]表示块i到块j的答案,然后再记录出现次数的前缀和,用讨论散块对答案的影响;
1 #include<bits/stdc++.h> 2 #define rg register 3 #define il inline 4 using namespace std; 5 const int N=100010,M=320; 6 int n,m,q,c[M][N],d[M][M],tmp[N],bl[N],a[N],u,len,st[M],ed[M]; 7 il char gc(){ 8 static char*p1,*p2,s[1000000]; 9 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 10 return(p1==p2)?EOF:*p1++; 11 } 12 il int rd(){ 13 int x=0; char ch=gc(); 14 while(ch<'0'||ch>'9')ch=gc(); 15 while(ch>='0'&&ch<='9')x=(x<<1)+(x<<3)+ch-'0',ch=gc(); 16 return x; 17 } 18 il int query(int x,int y){ 19 int re=0,num; 20 if(bl[x]==bl[y]){ 21 for(rg int i=x;i<=y;i++){ 22 if(++tmp[a[i]]==1)continue; 23 if(tmp[a[i]]&1)re--;else re++; 24 } 25 for(rg int i=x;i<=y;i++)tmp[a[i]]=0; 26 }else{ 27 if(bl[x]+1<bl[y])re=d[bl[x]+1][bl[y]-1]; 28 for(rg int i=x;i<=ed[bl[x]];i++){ 29 num = c[bl[y]-1][a[i]] - c[bl[x]][a[i]] + (++tmp[a[i]]); 30 if(num==1)continue; 31 if(num&1)re--;else re++; 32 } 33 for(rg int i=st[bl[y]];i<=y;i++){ 34 num = c[bl[y]-1][a[i]] - c[bl[x]][a[i]] + (++tmp[a[i]]); 35 if(num==1)continue; 36 if(num&1)re--;else re++; 37 } 38 for(rg int i=x;i<=ed[bl[x]];i++)tmp[a[i]]=0; 39 for(rg int i=st[bl[y]];i<=y;i++)tmp[a[i]]=0; 40 } 41 return re; 42 } 43 int main(){ 44 freopen("bzoj2821.in","r",stdin); 45 freopen("bzoj2821.out","w",stdout); 46 n=rd(); m=rd(); q=rd(); 47 u=sqrt(n),len=(n-1)/u+1; 48 for(rg int i=1;i<=n;i++)a[i]=rd(),bl[i]=(i-1)/u+1; 49 for(rg int i=1;i<=len;i++){ 50 st[i]=(i-1)*u+1,ed[i]=min(i*u,n); 51 for(rg int j=st[i];j<=ed[i];j++)tmp[a[j]]++; 52 for(rg int j=1;j<=m;j++)c[i][j]=tmp[j]; 53 } 54 for(rg int i=1;i<=len;i++){ 55 int now=0; 56 for(rg int j=1;j<=m;j++)tmp[j]=0; 57 for(rg int j=i;j<=len;j++){ 58 for(rg int k=st[j];k<=ed[j];k++){ 59 if((++tmp[a[k]])==1)continue; 60 if(tmp[a[k]]&1)now--;else now++; 61 } 62 d[i][j]=now; 63 } 64 } 65 for(rg int i=1;i<=m;i++)tmp[i]=0; 66 int ans=0; 67 for(rg int i=1;i<=q;i++){ 68 int l=(rd()+ans)%n+1,r=(rd()+ans)%n+1; 69 if(l>r)swap(l,r); 70 ans=query(l,r); 71 printf("%d\n",ans); 72 } 73 return 0; 74 }
bzoj2724
区间众数,强制在线; https://wenku.baidu.com/view/99bf0fc78662caaedd3383c4bb4cf7ec4afeb628.html
不带修和上一个一样;预处理整块出现次数的前缀和,枚举散块
带修的话修改一下分块大小暴力改,分块大小为$n^{\frac{2}{3}}$,复杂度为$O( n^{ \frac{5}{3} } )$ ;
1 #include<bits/stdc++.h> 2 #define il inline 3 #define rg register 4 using namespace std; 5 const int N=40010,M=210; 6 int n,m,c[M][N],d[M][M],tmp[N],sub[N],tot,a[N],bl[N]; 7 il char gc(){ 8 static char*p1,*p2,s[1000000]; 9 if(p1==p2)p2=(p1=s)+fread(s,1,1000000,stdin); 10 return(p1==p2)?EOF:*p1++; 11 } 12 il int rd(){ 13 int x=0,f=1; char C=gc(); 14 while(C<'0'||C>'9'){C=gc();if(C=='-')f=-1;} 15 while(C>='0'&&C<='9'){x=x*10+C-'0',C=gc();} 16 return x*f; 17 } 18 int main(){ 19 freopen("bzoj2724.in","r",stdin); 20 freopen("bzoj2724.out","w",stdout); 21 n=rd(); m=rd(); 22 int u = sqrt(n) , len = (n-1)/u+1; 23 for(rg int i=1;i<=n;i++)a[i]=sub[i]=rd(),bl[i]=(i-1)/u+1; 24 sort(sub+1,sub+n+1); 25 tot=unique(sub+1,sub+n+1)-sub-1; 26 for(rg int i=1;i<=n;i++)a[i]=lower_bound(sub+1,sub+tot+1,a[i])-sub; 27 for(rg int i=1;i<=len;i++){ 28 int li=u*(i-1)+1,ri=u*i; 29 for(rg int j=li;j<=ri;j++)tmp[a[j]]++; 30 for(rg int j=1;j<=tot;j++)c[i][j]=tmp[j]; 31 } 32 for(rg int i=1;i<=len;i++){ 33 int mxv=0,mxd=0; 34 for(rg int j=1;j<=tot;j++)tmp[j]=0; 35 for(rg int j=i;j<=len;j++){ 36 int lj=u*(j-1)+1,rj=u*j; 37 for(rg int k=lj;k<=rj;k++){ 38 tmp[a[k]]++; 39 if(tmp[a[k]]>mxv||(tmp[a[k]]==mxv&&a[k]<mxd)){ 40 mxd=a[k],mxv=tmp[a[k]]; 41 } 42 } 43 d[i][j]=mxd; 44 } 45 } 46 for(rg int j=1;j<=tot;j++)tmp[j]=0; 47 int ans=0,mx=0; 48 for(rg int i=1;i<=m;i++){ 49 int l=(rd()+ans-1)%n+1,r=(rd()+ans-1)%n+1; 50 if(l>r)swap(l,r); 51 if(bl[l]==bl[r]){ 52 ans=0;mx=0; 53 for(rg int j=l;j<=r;j++){ 54 tmp[a[j]]++; 55 if(tmp[a[j]]>mx||(tmp[a[j]]==mx&&a[j]<ans)){ 56 ans=a[j],mx=tmp[a[j]]; 57 } 58 } 59 for(rg int j=l;j<=r;j++)tmp[a[j]]=0; 60 }else{ 61 int t=bl[l]*u;for(rg int j=l;j<=t;j++)tmp[a[j]]++; 62 t=(bl[r]-1)*u+1;for(rg int j=t;j<=r;j++)tmp[a[j]]++; 63 if(bl[l]<bl[r]-1)ans=d[bl[l]+1][bl[r]-1],mx=tmp[ans]+c[bl[r]-1][ans]-c[bl[l]][ans]; 64 else ans=0,mx=0; 65 t=bl[l]*u;for(rg int j=l;j<=t;j++){ 66 int now=tmp[a[j]]+c[bl[r]-1][a[j]]-c[bl[l]][a[j]]; 67 if(now>mx||(now==mx&&a[j]<ans)){ 68 mx=now;ans=a[j]; 69 } 70 tmp[a[j]]=0; 71 } 72 t=(bl[r]-1)*u+1;for(rg int j=t;j<=r;j++){ 73 int now=tmp[a[j]]+c[bl[r]-1][a[j]]-c[bl[l]][a[j]]; 74 if(now>mx||(now==mx&&a[j]<ans)){ 75 mx=now;ans=a[j]; 76 } 77 tmp[a[j]]=0; 78 } 79 } 80 ans=sub[ans]; 81 printf("%d",ans); 82 puts(""); 83 //printf(" %d %d\n",l,r); 84 } 85 return 0; 86 }