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 }

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

转载于:https://www.cnblogs.com/Msmw/p/11344385.html

hzw的数列分块入门相关推荐

  1. #6279. 数列分块入门 3(区间修改,查询权值前驱)

    #6279. 数列分块入门 3 这是使用hzwer建议的set写的分块代码,set自动排序,支持二分查找,但是常数较大,比我下面写的用vector实现的分块慢了三倍,空间大了10倍. #include ...

  2. LOJ 数列分块入门6

    LOJ 数列分块入门6 题目: 题目 题解: 我都不懂这题为什么要用分块... ... 直接vector就好了... 但是如果有区间修改的话就不行了.所以这题是启示我们也可以动态分块.具体就是每次插入 ...

  3. LOJ #6280. 数列分块入门 4-分块(区间加法、区间求和)

    #6280. 数列分块入门 4 内存限制:256 MiB时间限制:500 ms标准输入输出 题目类型:传统评测方式:文本比较 上传者: hzwer 提交提交记录统计测试数据讨论 题目描述 给出一个长为 ...

  4. 数列分块入门(套题)(loj6277,loj6278,loj6279,loj6280,loj6281,loj6282,loj6283,loj6284,loj6285)

    前言 zjoi考差了,码一些分块题缓解一下心情 壹 数列分块入门 1[loj6277] 题目大意:区间加,单点查 直接分块,区间加时完全覆盖的块打tag,边界块暴力重构 块大小设为n\sqrt nn​ ...

  5. 数列分块入门 (1 ~ 7)

    分块 6277. 数列分块入门 1 分块思想 我们把每m个元素分成一块,所以我们总共的块数就是n/mn / mn/m块,一般情况下我们取m=nm = \sqrt{n}m=n​.对于区间加操作,我们可以 ...

  6. 「分块」数列分块入门1 – 9

    ACM模板 放暑假了,回归!!! 自己不会写暴力,而且好久没写代码了,于是学学分块的优雅暴力~ 「分块入门-LibreOJ」 「分块」数列分块入门1 – 9 by hzwer 数列简单分块问题实际上有 ...

  7. 「分块系列」数列分块入门3 解题报告

    数列分块入门3 题意概括 区间加法,区间求前驱. 写在前面 这题的方法与分块2方法极其类似,建议自行解决. 正题 和上一题类似,但是二分不是用来计数的,而是用来求小于c的最大值的.然后对于不完整快,将 ...

  8. #6277. 数列分块入门 1

    题目链接:https://loj.ac/problem/6277 学习博客:http://hzwer.com/8053.html #6277. 数列分块入门 1 内存限制:256 MiB时间限制:10 ...

  9. #6279. 数列分块入门 3

    数列分块入门 3 #include<bits/stdc++.h> using namespace std; #define ll long long const int N=1000010 ...

最新文章

  1. 【小白的CFD之旅】20 计算区域的构建
  2. 测试软件Postman下载(亲测有效)
  3. 2008下php上传文件崩溃,php – 当用户反复尝试上传无效文件类型时,网站崩溃
  4. [Leetcode][第95题][JAVA][不同的二叉搜索树 II][递归]
  5. container_of宏定义分析---linux内核
  6. display: flex的兼容性写法
  7. 2021年中国蛋鸡养殖设备市场趋势报告、技术动态创新及2027年市场预测
  8. 编辑请求内容 Charles
  9. 计算机应用excel题,计算机应用操作练习题-Excel
  10. 第九章 CSS-DOM
  11. Android官方开发文档下载
  12. 信息检索-矩阵理论与线性代数
  13. jq ajax读取txt,使用JQuery或Ajax加载.txt文件
  14. 蓝屏出现STOP:0X00000077是什么原因造成
  15. c++ 的绝对值函数
  16. LVGL lv_msgbox消息对话框(22)
  17. 视频目标检测paper带读(一)《Flow-Guided Feature Aggregation for Video Object Detection》
  18. iOS模拟器运行报错Unable to install /xxx/build/ios/iphonesimulator/Runner.app
  19. 从共识算法开谈 - 硬盘性能的最大几个误解
  20. 单载波频域均衡matlab仿真,包括卷积编码维特比译码,矩阵交织,QPSK调制解调,导频插入,MMSE-FDE频域均衡

热门文章

  1. 创建自己免费的论坛、博客网站
  2. 【Esp32】Esp32+sx1268 Spi接口驱动SX1268模块
  3. 使用NoneBot2可视化平台搭建QQ聊天机器人:本地和云部署教程
  4. 使用SurfaceView实现飘赞动画
  5. Python使用opencv打开笔记本摄像头时遇到的问题及解决办法
  6. powershell中替换文件内容的方法
  7. win10系统 鼠标放在开始或者任务栏就一直转圈圈
  8. matlab 场仿真,利用MATLAB软件实现温度场的仿真
  9. 有关Scrollview嵌套ListView的那些事
  10. Linux MTD是什么??