hzw的数列分块入门

T1

数列区间修改,单点查询。线段树,树状数组都可。(代码抄的)

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const int maxn=5e4+5;
 7 
 8 int n,blo;
 9 int v[maxn],bl[maxn],atag[maxn];
10 
11 void add(int a,int b,int c){
12     for(int i=a;i<=min(bl[a]*blo,b);i++)
13         v[i]+=c;
14     if(bl[a]!=bl[b])
15         for(int i=(bl[b]-1)*blo+1;i<=b;i++)
16             v[i]+=c;
17     for(int i=bl[a]+1;i<=bl[b]-1;i++)
18         atag[i]+=c;
19 }
20 
21 int main()
22 {
23     scanf("%d",&n);blo=sqrt(n);
24     for(int i=1;i<=n;i++) scanf("%d",&v[i]);
25     for(int i=1;i<=n;i++) bl[i]=(i-1)/blo+1;
26     for(int i=1;i<=n;i++) 
27     {
28         int op,a,b,c;
29         scanf("%d%d%d%d",&op,&a,&b,&c);
30         if(op==0) add(a,b,c);
31         if(op==1) printf("%d\n",v[b]+atag[bl[b]]);
32     }
33     return 0;
34 }

 

 T2

统计区间比c*c小的个数

同样线段树也可以做,维护区间小于c*c的个数

分块的话,因为要找区间小于c*c的数,所以对于两个端点所在的block,每次修改后要重新排序,才能通过二分查找到小于c*c的个数。

复杂度:O(nlogn + n√nlog√n)

ps:这个题用分块的话换个姿势就T (╥﹏╥)

 1 #include <bits/stdc++.h>
 2 
 3 using namespace std;
 4 
 5 typedef long long ll;
 6 const int maxn=5e4+5;
 7 
 8 int n,blo;
 9 int v[maxn],bl[maxn],atag[maxn];
10 
11 vector <int> V[505];
12 
13 inline int read()
14 {
15     char ch=getchar();int x=0,f=0;
16     while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
17     while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
18     return f?-x:x;
19 }
20 
21 void reset(int x)
22 {
23     V[x].clear();
24     for(int i=(x-1)*blo+1;i<=min(x*blo,n);i++)
25         V[x].push_back(v[i]);
26     sort(V[x].begin(),V[x].end());
27 }
28 
29 void add(int a,int b,int c){
30     for(int i=a;i<=min(b,bl[a]*blo);i++)
31         v[i]+=c;
32     reset(bl[a]);
33     if(bl[a]!=bl[b]){
34         for(int i=(bl[b]-1)*blo+1;i<=b;i++){
35             v[i]+=c;
36         }
37         reset(bl[b]);
38     }
39 
40     for(int i=bl[a]+1;i<=bl[b]-1;i++){
41         atag[i]+=c;
42     }
43 }
44 
45 
46 int query(int a,int b,int c){
47     int ans=0;
48     for(int i=a;i<=min(b,bl[a]*blo);i++)
49         if(v[i]+atag[bl[a]]<c*c) ans++;
50     if(bl[a]!=bl[b])
51         for(int i=(bl[b]-1)*blo+1;i<=b;i++)
52             if(v[i]+atag[bl[b]]<c*c) ans++;
53     
54     for(int i=bl[a]+1;i<=bl[b]-1;i++){
55         int tmp=c*c-atag[i];
56         ans+=lower_bound(V[i].begin(),V[i].end(),tmp)-V[i].begin();
57     }
58     return ans;
59 }
60 
61 
62 
63 int main()
64 {
65     n=read();blo=sqrt(n);
66     for(int i=1;i<=n;i++) v[i]=read(); 
67     for(int i=1;i<=n;i++) {bl[i]=(i-1)/blo+1;V[bl[i]].push_back(v[i]);}
68     for(int i=1;i<=bl[n];i++) sort(V[i].begin(),V[i].end());
69     for(int i=1;i<=n;i++) {
70         int op,a,b,c;op=read();a=read();b=read();c=read();
71         if(op==0) add(a,b,c);
72             else printf("%d\n",query(a,b,c));
73     } 
74     return 0;
75 }

T3

这个题换个姿势就wa,真的变一变就wa。所以代码又是抄的(o(╥﹏╥)o),我好菜啊!

块内用set去重,找最大的值。

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=1e5+5;
 5 
 6 inline int read()
 7 {
 8     char ch=getchar();int x=0,f=0;
 9     while(ch<'0' || ch>'9') f|=ch=='-',ch=getchar();
10     while(ch>='0' && ch<='9') x=x*10+ch-'0',ch=getchar();
11     return f?-x:x;
12 }
13 
14 int n,blo;
15 int v[maxn],bl[maxn],atag[maxn];
16 set<int>st[105];
17 
18 void add(int a,int b,int c)
19 {
20     for(int i=a;i<=min(bl[a]*blo,b);i++)
21     {
22         st[bl[a]].erase(v[i]);
23         v[i]+=c;
24         st[bl[a]].insert(v[i]);
25     }
26     if(bl[a]!=bl[b])
27     {
28         for(int i=(bl[b]-1)*blo+1;i<=b;i++)
29         {
30             st[bl[b]].erase(v[i]);
31             v[i]+=c;
32             st[bl[b]].insert(v[i]);
33         }
34     }
35     for(int i=bl[a]+1;i<=bl[b]-1;i++)
36         atag[i]+=c;
37 }
38 
39 
40 int query(int a,int b,int c)
41 {
42     int ans=-1;
43     for(int i=a;i<=min(bl[a]*blo,b);i++)
44     {
45         int val=v[i]+atag[bl[a]];
46         if(val<c)ans=max(val,ans);
47     }
48     if(bl[a]!=bl[b])        
49         for(int i=(bl[b]-1)*blo+1;i<=b;i++)        
50         {
51             int val=v[i]+atag[bl[b]];
52             if(val<c)ans=max(val,ans);
53         }
54     for(int i=bl[a]+1;i<=bl[b]-1;i++)
55     {
56         int x=c-atag[i];
57         set<int>::iterator it=st[i].lower_bound(x);
58         if(it==st[i].begin())continue;
59         --it;
60         ans=max(ans,*it+atag[i]);
61     }
62     return ans;
63 }
64 
65 int main()
66 {
67     n=read();blo=1000;
68     for(int i=1;i<=n;i++)v[i]=read();
69     for(int i=1;i<=n;i++)
70     {
71         bl[i]=(i-1)/blo+1;
72         st[bl[i]].insert(v[i]);
73     }
74     for(int i=1;i<=n;i++)
75     {
76         int f=read(),a=read(),b=read(),c=read();
77         if(f==0)add(a,b,c);
78         if(f==1)printf("%d\n",query(a,b,c));
79     }
80     return 0;
81 }

 T4

简单区间修改取模。

分块竟然比线段树要快

线段树:

 1 #include <bits/stdc++.h>
 2 #define lson l,m,rt<<1
 3 #define rson m+1,r,rt<<1|1
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=5e4+5;
 7 
 8 ll sum[maxn<<2];
 9 ll f[maxn<<2];
10 
11 ll read()
12 {
13     ll x=0,f=1;char ch=getchar();
14     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
15     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
16     return x*f;
17 }
18 
19 void pushdown(int rt,int m){
20     if(f[rt]!=0){
21         sum[rt<<1]+=(m-(m>>1))*f[rt];
22         sum[rt<<1|1]+=(m>>1)*f[rt];
23         f[rt<<1]+=f[rt];f[rt<<1|1]+=f[rt];
24         f[rt]=0;
25     }
26 }
27 
28 void build(int l,int r,int rt){
29     if(l==r)
30     {
31         sum[rt]=read();
32         f[rt]=0;
33         return ;
34     }
35     f[rt]=0;
36     int m=(l+r)>>1;
37     build(lson);
38     build(rson);
39     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
40 }
41 
42 
43 void update(int L,int R,int c,int l,int r,int rt){
44     if(L<=l&&R>=r)
45     {
46         sum[rt]+=(r-l+1)*c;
47         f[rt]+=c;
48         return; 
49     }
50     int m=(l+r)>>1;
51     pushdown(rt,r-l+1);
52     if(L<=m) update(L,R,c,lson);
53     if(R>m) update(L,R,c,rson);
54     sum[rt]=sum[rt<<1]+sum[rt<<1|1];
55 }
56 
57 
58 ll query(int L,int R,int l,int r,int rt){
59     if(L<=l&&R>=r)
60     {
61         return sum[rt];
62     }
63     int m=(l+r)>>1;
64     pushdown(rt,r-l+1);
65     ll res=0;
66     if(L<=m) res+=query(L,R,lson);
67     if(R>m) res+=query(L,R,rson);
68     return res;
69 }
70 
71 
72 int main(){
73     int n;n=read();
74     build(1,n,1);
75     for(int i=1;i<=n;i++){
76         int op,a,b,c;
77         op=read();a=read();b=read();c=read();
78         if(op==0) update(a,b,c,1,n,1);
79         else if(op==1) printf("%lld\n",query(a,b,1,n,1)%(c+1));
80     }
81     return 0;
82 }
View Code

分块:

 1 #include <bits/stdc++.h>
 2 #define lson l,m,rt<<1
 3 #define rson m+1,r,rt<<1|1
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=5e4+5;
 7 
 8 ll read()
 9 {
10     ll x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 
16 int n,blog;
17 ll v[maxn],bl[maxn],ata[maxn],sum[maxn];
18 
19 
20 void add(int a,int b,int c){
21     for(int i=a;i<=min((ll)b,bl[a]*blog);i++)
22         v[i]+=c,sum[bl[a]]+=c;
23     if(bl[a]!=bl[b])
24         for(int i=(bl[b]-1)*blog+1;i<=b;i++)
25             v[i]+=c,sum[bl[b]]+=c;
26     for(int i=bl[a]+1;i<=bl[b]-1;i++)
27         ata[i]+=c;
28 }
29 
30 ll query(int a,int b){
31     ll ans=0;
32     for(int i=a;i<=min((ll)b,bl[a]*blog);i++)
33         ans+=v[i]+ata[bl[a]];
34     if(bl[a]!=bl[b])
35         for(int i=((bl[b]-1)*blog+1);i<=b;i++)
36             ans+=v[i]+ata[bl[b]];
37     for(int i=bl[a]+1;i<=bl[b]-1;i++)
38         ans+=(ata[i]*blog)+sum[i];
39     return ans;
40 }        
41 
42 int main(){
43     n=read(); blog=sqrt(n);
44     for(int i=1;i<=n;i++)
45     {
46         v[i]=read();
47         bl[i]=(i-1)/blog+1;
48         sum[bl[i]]+=v[i];
49     }
50     cout <<endl;
51     for(int i=1;i<=n;i++){
52         int op,a,b,c;
53         op=read();a=read();b=read();c=read();
54         if(op==0) 
55             add(a,b,c);
56         else if(op==1) printf("%lld\n",query(a,b)%(c+1));
57     }    
58     
59     return 0;
60 }
View Code

分块还是写的磕磕绊绊,这么简单还是调了好长时间

T5

区间求和,修改为区间元素开方

之前用线段树做过一次,就是因为对于 a[i]<=2^31-1,最多开方次数为5次,之后就不会再变化,所以根据这个性质,对于还可以变化的整区间暴力修改。散区间也暴力修改

 1 #include <bits/stdc++.h>
 2 #define lson l,m,rt<<1
 3 #define rson m+1,r,rt<<1|1
 4 using namespace std;
 5 typedef long long ll;
 6 const int maxn=5e4+5;
 7 
 8 ll read()
 9 {
10     ll x=0,f=1;char ch=getchar();
11     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
12     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
13     return x*f;
14 }
15 
16 int n,blog;
17 ll v[maxn],bl[maxn],vis[maxn],sum[maxn];
18 
19 void add(int a,int b){
20     for(int i=a;i<=min((ll)b,bl[a]*blog);i++){
21         sum[bl[a]]-=v[i];
22         v[i]=sqrt(v[i]);
23         sum[bl[a]]+=v[i];
24     }
25     if(bl[a]!=bl[b])
26         for(int i=(bl[b]-1)*blog+1;i<=b;i++){
27             sum[bl[b]]-=v[i];
28             v[i]=sqrt(v[i]);
29             sum[bl[b]]+=v[i];
30         }
31     for(int i=bl[a]+1;i<=bl[b]-1;i++)
32     {
33         if(vis[i]==1) continue;
34         sum[i]=0;
35         vis[i]=1;
36         for(int j=(i-1)*blog+1;j<=i*blog;j++)
37         {
38             v[j]=sqrt(v[j]);sum[i]+=v[j];
39             if(v[j]>1) vis[i]=0;
40         }
41     }
42 }
43 
44 ll query(int a,int b){
45     ll ans=0;
46     for(int i=a;i<=min((ll)b,bl[a]*blog);i++)
47     {
48         ans+=v[i];    
49     }
50     if(bl[a]!=bl[b])
51         for(int i=((bl[b]-1)*blog+1);i<=b;i++)
52         {
53             ans+=v[i];
54         }
55     for(int i=bl[a]+1;i<=bl[b]-1;i++)    
56     {
57         ans+=sum[i];
58     }
59     return ans;
60 }        
61 
62 int main(){
63     n=read(); blog=sqrt(n);
64     for(int i=1;i<=n;i++)
65     {
66         v[i]=read();
67         bl[i]=(i-1)/blog+1;
68         sum[bl[i]]+=v[i];
69     }
70     for(int i=1;i<=n;i++){
71         int op,a,b,c;
72         op=read();a=read();b=read();c=read();
73         if(op==0) 
74             add(a,b);
75         else if(op==1) printf("%lld\n",query(a,b));
76     }    
77     
78     return 0;
79 }
View Code
 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int maxn=1e5+5;
 5 int blo,n;
 6 int v[maxn];int bl[maxn];
 7 
 8 vector <int> V[maxn];
 9 
10 ll read()
11 {
12     ll x=0,f=1;char ch=getchar();
13     while(ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
14     while(ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
15     return x*f;
16 }
17 
18 void ope(int a,int b){
19     ll cnt=0;int x=1;
20     for(int i=1;i<=n;i++)
21     {
22         if(cnt+V[i].size()<a) cnt+=V[i].size();
23             else
24             {
25                 x=i;
26                 break;
27             }
28     }
29     cnt=a-cnt;
30     vector <int> :: iterator it=V[x].begin();
31     V[x].insert(it+cnt-1,b);
32 }
33 
34 int query(int a){
35     ll cnt=0;int x=1;
36     for(int i=1;i<=n;i++){
37         if(cnt+V[i].size()<a) cnt+=V[i].size();
38             else{
39                 x=i;
40                 break;
41             }
42     }
43     cnt=a-cnt;
44     return V[x][cnt-1];
45 }
46 
47 int main(){ 
48     n=read();blo=sqrt(n);
49     for(int i=1;i<=n;i++)
50     {
51         v[i]=read();
52         bl[i]=(i-1)/blo+1;
53         V[bl[i]].push_back(v[i]);
54     }
55     
56     for(int i=1;i<=n;i++)
57     {
58         int op,a,b,c;
59         op=read();a=read();b=read();c=read();
60         if(op==0) ope(a,b);
61         else if(op==1) printf("%d\n",query(b)); 
62     }
63     return 0;
64 }

 

 

没有想到其它做法,区间没有重构,水过

posted @ 2019-08-13 10:36  Chuhanjing  阅读(260)  评论(0编辑  收藏  举报