【习题整理】分块+莫队(未完待续)

注意:这是一篇十分劣质的博客,只有题目和简单的几句话,慎用。。。。。。。。。。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 }
bzoj2957

 


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 } 
bzoj2141

 


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 }
bzoj2821

 

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 }
bzoj2724

 

转载于:https://www.cnblogs.com/Paul-Guderian/p/10093651.html

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值