题意:维护一个数列,给出维护区间加法,询问区间内大于等于某个值的元素个数。

算法:分块。因为本题第二问显然可以用二分的思想,但是这貌似并不符合区间可加性,线段树好像就不好用了呢。所以本蒟蒻学习了分块。

这大概是本蒟蒻的第一题正式分块,思想是在hzwer学长的分块入门学的==。

什么是分块?我们维护数列(貌似树上也可以)信息时可以先采用分治的思想,把数列分成若干连续的块,维护信息可以统一在块上进行维护。假如有一个n元素的数列,根据均值不等式的数学知识(并不会证明),我们把每个块的大小设为根号n可以达到最右效果。但是显然有时根号n并不是整数==,没有关系,我们的数列上大部分都在整块上,只有小部分被遗弃的元素在不完整的块中。

我们进行区间操作时,把在整块中的元素进行整体操作,那些在不完整的块中的元素进行暴力操作

总结来说,就是“大块维护,小段朴素”,这也是分块最基本的思想。

分块的复杂度(根号算法)虽然较其他数据结构可能略高了一些,却是打暴力的好方法,思维较简单,处理问题的范围更广,码量...可能略大(?)

回到本题的两个操作:

区间加法:对于一段区间,如果存在被整块覆盖的情况,直接在整块的加法标记上记录,不需在原序列上改动,查询时在加上加法标记;而在不完整的块中的元素,直接暴力修改。

查询大于等于X的元素个数:想一想如果数列是无序的,我们分的块就完全没用了。但是如果我们在预处理时以及修改时对每个整块进行排序,查询时调用lower_bound/手写二分查找,问题就能轻松得到解决。那些在不完整块中的元素,同理,暴力枚举统计。

综上,我们不难发现,使用分块算法需要或者只需要想的两个关键:

  怎么维护整块?怎么维护不完整的块?

分块的更多代码实现细节:

  (几乎每到分块题都要的)bl[i]记录i在第几个块

  bl[i]*blo(blo=sqrt(n))可以得出当前位置(块的右边界),在此基础上变形

  右边界:取min,bl[l]*blo,n(防止越界)

Code

 // luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector> using namespace std; int n,Q,blo;
int val[],bl[],addtag[];
char opt[];
vector<int>cnt[]; void update(int x)
{
cnt[x].clear();
for(int i=(x-)*blo+;i<=min(x*blo,n);i++)
cnt[x].push_back(val[i]);
sort(cnt[x].begin(),cnt[x].end());
} void add(int l,int r,int p)
{
if(l==r) val[l]+=p;
else
{
for(int i=l;i<=min(bl[l]*blo,r);i++)
val[i]+=p;
update(bl[l]);
if(bl[l]!=bl[r])
{
for(int i=(bl[r]-)*blo+;i<=r;i++)
val[i]+=p;
update(bl[r]);
}
for(int i=bl[l]+;i<=bl[r]-;i++)
addtag[i]+=p;
}
} int query(int l,int r,int p)
{
int ans=;
for(int i=l;i<=min(bl[l]*blo,r);i++)
if(val[i]+addtag[bl[l]]>=p) ans++;
if(bl[l]!=bl[r])
{
for(int i=(bl[r]-)*blo+;i<=r;i++)
if(val[i]+addtag[bl[r]]>=p) ans++;
}
for(int i=bl[l]+;i<=bl[r]-;i++)
{
int tmp=p-addtag[i];
int pos=lower_bound(cnt[i].begin(),cnt[i].end(),tmp)-cnt[i].begin();
ans+=blo-pos;
// ans+=find(i,tmp);
}
return ans;
} int main()
{
scanf("%d%d",&n,&Q);
for(int i=;i<=n;i++) scanf("%d",&val[i]);
blo=sqrt(n);
for(int i=;i<=n;i++)
{
bl[i]=(i-)/blo+;
cnt[bl[i]].push_back(val[i]);
}
for(int i=;i<=bl[n];i++)
sort(cnt[i].begin(),cnt[i].end());
while(Q--)
{
scanf("%s",opt+);
int x=,y=,z=;
scanf("%d%d%d",&x,&y,&z);
if(opt[]=='M')
add(x,y,z);
else if(opt[]=='A')
printf("%d\n",query(x,y,z));
}
return ;
}

代码纯享版

 // luogu-judger-enable-o2
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<vector> using namespace std; int n,Q,blo;
int val[],bl[],addtag[];
char opt[];
vector<int>cnt[]; void update(int x)//针对散块
{//清空,重新读入
cnt[x].clear();
for(int i=(x-)*blo+;i<=min(x*blo,n);i++)
cnt[x].push_back(val[i]);
sort(cnt[x].begin(),cnt[x].end());
} void add(int l,int r,int p)
{
if(l==r) val[l]+=p;
else
{
for(int i=l;i<=min(bl[l]*blo,r);i++)
val[i]+=p;//左散块
update(bl[l]);//重新排序
if(bl[l]!=bl[r])
{//右散块
for(int i=(bl[r]-)*blo+;i<=r;i++)
val[i]+=p;
update(bl[r]);
}
//整块
for(int i=bl[l]+;i<=bl[r]-;i++)
addtag[i]+=p;
}
} int query(int l,int r,int p)
{
int ans=;
//左半散块
for(int i=l;i<=min(bl[l]*blo,r);i++)
if(val[i]+addtag[bl[l]]>=p) ans++;
if(bl[l]!=bl[r])// !
{//右半散块
for(int i=(bl[r]-)*blo+;i<=r;i++)
if(val[i]+addtag[bl[r]]>=p) ans++;
}
for(int i=bl[l]+;i<=bl[r]-;i++)//整块
{
int tmp=p-addtag[i];//求>=p,则先把加法标记减去
int pos=lower_bound(cnt[i].begin(),cnt[i].end(),tmp)-cnt[i].begin();
ans+=blo-pos;//注意这句 精髓
// ans+=find(i,tmp);
}
return ans;
} int main()
{
scanf("%d%d",&n,&Q);
for(int i=;i<=n;i++) scanf("%d",&val[i]);
blo=sqrt(n);
for(int i=;i<=n;i++)
{
bl[i]=(i-)/blo+;
cnt[bl[i]].push_back(val[i]);//记录每个块中元素
}
//对每个块中元素进行排序
for(int i=;i<=bl[n];i++)
sort(cnt[i].begin(),cnt[i].end());
while(Q--)
{
scanf("%s",opt+);
int x=,y=,z=;
scanf("%d%d%d",&x,&y,&z);
if(opt[]=='M')
add(x,y,z);
else if(opt[]=='A')
printf("%d\n",query(x,y,z));
}
return ;
}

贴心注释版

然鹅不吸氧会T掉一个点,可能是我lowerbound常数的锅锅?讨论里有人说要用longlong结果我用了longlong只会带来无端的CE/WA/RE。

Just be cautious.

bzoj3343 教主的魔法【分块入门】By cellur925的更多相关文章

  1. BZOJ3343: 教主的魔法 分块

    2016-05-28  10:27:19 题目:http://www.lydsy.com/JudgeOnline/problem.php?id=3343 比较显然的分块题,分块后块内排序,维护整块的附 ...

  2. P2801 教主的魔法(分块入门)

    两个月之前听yyr学长讲的分块,感觉是个很神奇的暴力,但到现在还是懵的一匹 #include<bits/stdc++.h> using namespace std; ; int belon ...

  3. [bzoj3343]教主的魔法——分块

    Brief description 给定一个数列,您需要支持一下两种操作: 给[l,r]同加一个数 询问[l,r]中有多少数字大于或等于v Algorithm analyse 这个题一时想不到什么有效 ...

  4. BZOJ-3343教主的魔法+分块(大块排序二分)

    传送门:https://www.luogu.org/problemnew/show/P2801 参考:http://hzwer.com/2784.html  感觉思路无比清晰:) ps:我在洛谷A的, ...

  5. bzoj3343: 教主的魔法 分块 标记

    修改:两边暴力重构,中间打标记.复杂度:O(n0.5) 查询:中间二分两边暴力.O(n0.5logn0.5) 总时间复杂度O(n*n0.5logn0.5) 空间复杂度是n级别的 标记不用下传因为标记不 ...

  6. [BZOJ3343]教主的魔法

    [BZOJ3343]教主的魔法 试题描述 教主最近学会了一种神奇的魔法,能够使人长高.于是他准备演示给XMYZ信息组每个英雄看.于是N个英雄们又一次聚集在了一起,这次他们排成了一列,被编号为1.2.… ...

  7. Luogu 2801 教主的魔法 | 分块模板题

    Luogu 2801 教主的魔法 | 分块模板题 我犯的错误: 有一处l打成了1,还看不出来-- 缩小块大小De完bug后忘了把块大小改回去就提交--还以为自己一定能A了-- #include < ...

  8. BZOJ 3343: 教主的魔法(分块+二分查找)

    BZOJ 3343: 教主的魔法(分块+二分查找) 3343: 教主的魔法 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 1172  Solved:  ...

  9. 【BZOJ-3343】教主的魔法 分块

    3343: 教主的魔法 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 950  Solved: 414[Submit][Status][Discuss ...

随机推荐

  1. Method Swizzling以及AOP编程:在运行时进行代码注入-b

    概述 今天我们主要讨论iOS runtime中的一种黑色技术,称为Method Swizzling.字面上理解Method Swizzling可能比较晦涩难懂,毕竟不是中文,不过你可以理解为“移花接木 ...

  2. mysql语法、特殊符号及正則表達式的使用

    http://blog.csdn.net/pipisorry/article/details/46773545 sql语言 结构化的查询语言.(Structured Query Language),是 ...

  3. 一套扁平化界面风格的flex 皮肤

    意外在git上发现这个项目.似乎刚開始不久.部分控件的新皮肤似乎还没完毕.只是个人感觉挺不错的.大家认为呢? =>git地址:https://github.com/akamud/FlatSpar ...

  4. java内部类的一些看法

    java内部类, 我在看<thinking in java>的时候总感觉模棱两可的, 挣扎了好几天之后, 感觉有一部分的问题想的清楚了, 写一个随笔记录一下, 以备以后修改和查看 什么是内 ...

  5. ArcGIS 10.3 for Server新特性介绍

    ArcGIS10.3的正式版立即在美国Esri全球用户大会推出.中国的正式发行时间预计在Esri中国的用户大会.以下就将用户比較关心的ArcGIS 10.3 for Server的新特性给大家进行简单 ...

  6. 翻译:A Tutorial on the Device Tree (Zynq) -- Part III

    A Tutorial on the Device Tree (Zynq) -- Part III 定义外设 可能你读本文是为了给你的设备写一个Linux驱动,在这方面要推荐著名的<Linux D ...

  7. Xcode6.1 Prefix.pch添加方式

     本文转载:http://blog.csdn.net/foolsong/article/details/40653497     在Xcode6.1中创建工程默认是没有Prefix.pch文件的,需要 ...

  8. Latex 5: LaTeX资料下载

    转: LaTeX资料下载 最全latex资料下载   LaTeX命令速查手册1  

  9. kbmMW实现sql查询(图文并茂)

    kbmMW对于Delphi来说,是最好的多层框架,没有之一,无论是效率.稳定及架构都让人无可挑剔,尤其自Delphi支持跨平台开发以来,随着Delphi支持ios及Android移动开发,KbmMW也 ...

  10. 浅谈js执行机制

    关于js执行机制,老早之前就一直想写篇文章做个总结,因为和js执行顺序的面试题碰到的特别多,每次碰到总是会去网上查,没有系统地总结,搞得每次碰到都是似懂非懂的感觉,这篇文章就系统的总结一下js执行机制 ...