Luogu P5309 [Ynoi2012]D1T1
小清新分块题,从头到尾都十分套路,和CXR大佬一起YY了一下就出来了
首先套路地设个阈值\(S\),把修改的\(x\)分成大于\(S\)和小于等于\(S\)两部分,然后我们考虑分别求解这两部分
\(x>S\)
这个应该是比较简单的一部分了吧,我们考虑到此时要修改的数也就\(\frac{n}{x}\)个,所以可以大力修改
但是如果用树状数组这样的东西来维护区间和那么复杂度就是修改\(\frac{n}{x}\cdot\log n\)的,而询问只有\(O(\log n)\),很不平衡
所以我们套路地用分块来维护单点修改,区间查询,这样这部分的总体复杂度就平衡到了\(O(m\cdot(\sqrt n+\frac{n}{S}))\)
然后刚开始的初始化也可以交给这一部分,这都是比较清新的
\(x\le S\)
说实话这部分其实也不难,因为我们仔细观察题目,每次修改的\(y\le x\)
那么也就意味这这次修改是把数组中所有下标\(\mod x\)与\(y\)同余的位置全部加了\(z\)
我们考虑固定\(x\)时的询问,那么一段区间\([l,r]\)其实包含了\(\lfloor\frac{r-l+1}{x}\rfloor\)个整个的区间,而这些区间内的和其实就是所有询问\(x\)固定的\(z\)的总和
剩下的一部分也很好算,其实就是求一个\(\mod x\)意义下的区间和(只用对\(y\mod x\)位置增加)
考虑到此时\(x\)的范围很小,因此我们大可以直接记一个前缀和,每次修改暴力修改整个后缀,这样复杂度总体是\(O(mS)\)的
总体分析
这个时候按照一般的套路我们总是取\(S=\sqrt n\)来达到理论最优的复杂度平衡
但是这里如果你这么写你可能就会得到TLE80的情况,其实是因为出题人为了卡暴力出了大量的\(x\le S\)的数据,而我们的算法在这部分的常数特别大
因此很简单,我们大可以调小\(S\)的值(推荐在\([30,50]\)中),然后就可以轻松地通过此题顺手抢了个Rank233
CODE
#include<cstdio>
#include<cctype>
#include<cmath>
#define RI register int
#define CI const int&
#define Tp template <typename T>
using namespace std;
const int N=200005,mod=1e9+7,S=40;
int n,m,a[N],opt,x,y,z,size;
class FileInputOutput
{
private:
static const int S=1<<21;
#define tc() (A==B&&(B=(A=Fin)+fread(Fin,1,S,stdin),A==B)?EOF:*A++)
#define pc(ch) (Ftop<S?Fout[Ftop++]=ch:(fwrite(Fout,1,S,stdout),Fout[(Ftop=0)++]=ch))
char Fin[S],Fout[S],*A,*B; int Ftop,pt[15];
public:
Tp inline void read(T& x)
{
x=0; char ch; while (!isdigit(ch=tc()));
while (x=(x<<3)+(x<<1)+(ch&15),isdigit(ch=tc()));
}
Tp inline void write(T x)
{
if (!x) return (void)(pc('0'),pc('\n')); RI ptop=0;
while (x) pt[++ptop]=x%10,x/=10; while (ptop) pc(pt[ptop--]+48); pc('\n');
}
inline void Fend(void)
{
fwrite(Fout,1,Ftop,stdout);
}
#undef tc
#undef pc
}F;
inline void inc(int& x,CI y)
{
if ((x+=y)>=mod) x-=mod;
}
inline int sum(CI a,CI b)
{
int t=a+b; return t>=mod?t-mod:t;
}
inline int sub(CI a,CI b)
{
int t=a-b; return t<0?t+mod:t;
}
namespace Case1 //Solver for z>sqrt(n)
{
const int BLO=450; int sum[BLO],blk[N];
inline void init(void)
{
for (RI i=1;i<=n;++i) inc(sum[blk[i]=(i-1)/size+1],a[i]);
}
inline void modify(CI x,CI y,CI z)
{
for (RI i=y;i<=n;i+=x) inc(a[i],z),inc(sum[blk[i]],z);
}
inline int BF(CI x,CI y,int ret=0)
{
for (RI i=x;i<=y;++i) inc(ret,a[i]); return ret;
}
inline int query(CI x,CI y,int ret=0)
{
if (blk[x]==blk[y]) return BF(x,y);
inc(ret,BF(x,blk[x]*size)); inc(ret,BF((blk[y]-1)*size+1,y));
for (RI i=blk[x]+1;i<blk[y];++i) inc(ret,sum[i]); return ret;
}
};
namespace Case2 //Solver for z<=sqrt(n)
{
int mv[S+5][S+5],sum[S+5],stack[N],top; bool vis[S+5];
inline void modify(CI x,CI y,CI z)
{
if (!vis[x]) vis[x]=1,stack[++top]=x;
for (RI i=y%x;i<x;++i) inc(mv[x][i],z); inc(sum[x],z);
}
inline int query(CI x,CI y,int ret=0)
{
for (RI i=1;i<=top;++i)
{
int p=stack[i],t=(y-x+1)/p; inc(ret,1LL*t*sum[p]%mod);
int l=x+t*p,r=y; if (l>r) continue; l%=p; r%=p;
if (l<=r) inc(ret,sub(mv[p][r],l?mv[p][l-1]:0)); else
inc(ret,mv[p][r]),inc(ret,sub(sum[p],l?mv[p][l-1]:0));
}
return ret;
}
};
int main()
{
//freopen("CODE.in","r",stdin); freopen("CODE.out","w",stdout);
RI i; for (F.read(n),F.read(m),i=1;i<=n;++i) F.read(a[i]);
for (size=(int)sqrt(n),Case1::init();m;--m)
{
F.read(opt); F.read(x); F.read(y);
if (opt^1) F.write(sum(Case1::query(x,y),Case2::query(x,y)));
else F.read(z),x>S?(Case1::modify(x,y,z),0):(Case2::modify(x,y,z),0);
}
return F.Fend(),0;
}
Luogu P5309 [Ynoi2012]D1T1的更多相关文章
- 洛谷P5524:[Ynoi2012]D1T1——题解
https://www.luogu.org/problem/P5524 看着能做就当线段树复健题了. 根据高中知识我们有 $sin(a+b)=sin(a)cos(b)+cos(a)sin(b)$ $c ...
- 【洛谷5309】[Ynoi2012] D1T1(分块)
点此看题面 大致题意: 两种操作,区间求和,将形如\(ax+y\)的位置的元素值加\(z\). 分块 这种题目显然就是按照\(x\)与\(\sqrt n\)的大小关系来分块. 对于\(x>\sq ...
- [Ynoi2012]D1T1
题目 套路的根号分治啊 我们设置一个值\(S\) 对于\(S\leq x\)的操作,我们直接暴力修改,显然这样只会修改\(\frac{n}{S}\)次,所以我们需要一个能够\(O(1)\)修改的数据结 ...
- 【题解】Luogu P5313 僕たちはひとつの光([Ynoi2012]D2T2)
原题传送门 lovelive好评 比赛时只拿到了60pts,还是自己太菜了 这题的思想实际有点像Luogu P3674 小清新人渣的本愿与Luogu P5071 [Ynoi2015]此时此刻的光辉 这 ...
- 【luogu P1351 联合权值】 题解
题目链接:https://www.luogu.org/problemnew/show/P1351 做了些提高组的题,不得不说虽然NOIP考察的知识点虽然基本上都学过,但是做起题来还是需要动脑子的. 题 ...
- 2017.10.1 国庆清北 D1T1 zhx的字符串题
题目背景 2017国庆清北D1T1 题目描述 你是能看到第一题的 friends 呢. ——hja 何大爷对字符串十分有研究,于是天天出字符串题虐杀 zhx.何大爷今天为 字符串定义了新的权值计算方法 ...
- Luogu 魔法学院杯-第二弹(萌新的第一法blog)
虽然有点久远 还是放一下吧. 传送门:https://www.luogu.org/contest/show?tid=754 第一题 沉迷游戏,伤感情 #include <queue> ...
- luogu p1268 树的重量——构造,真正考验编程能力
题目链接:http://www.luogu.org/problem/show?pid=1268#sub -------- 这道题费了我不少心思= =其实思路和标称毫无差别,但是由于不习惯ACM风格的题 ...
- [luogu P2170] 选学霸(并查集+dp)
题目传送门:https://www.luogu.org/problem/show?pid=2170 题目描述 老师想从N名学生中选M人当学霸,但有K对人实力相当,如果实力相当的人中,一部分被选上,另一 ...
随机推荐
- CentOS6.5系统挂载NTFS分区的硬盘
下载rpmforge,下载对应的版本,就是对应CentOS版本,还有32位与64位也要对应上.rpmforge拥有4000多种CentOS的软件包,被CentOS社区认为是最安全也是最稳定的一个软件仓 ...
- Alibaba(阿里) RocketMQ入门实例
摘自:码友18年(www.mayou18.com) what is rocketMQ? RocketMQ作为一款分布式的消息中间件(阿里的说法是不遵循任何规范的,所以不能完全用JMS的那一套东西来看它 ...
- Python web(Django)连接Sql server
(开开心心每一天~ ---虫瘾师) Python Web(Django) 与SQL SERVRE的连接----Come QQ群:607021567(里面有很多开源代码和资料,并且python的游戏也有 ...
- Jmeter4.0分布式测试时启动Jmeter.server时报错
最近又开始研究Jmeter,将新版本4.0下载下来体验,准备远程分布式测试,又出现一些问题,废话不多说,直入主题把! Windows 系统启动Jmeter 4.0的JmeterServer.ba ...
- Android SlidingMenu 使用详解
转载请标明出处:http://blog.csdn.net/lmj623565791/article/details/36677279 很多APP都有侧滑菜单的功能,部分APP左右都是侧滑菜单~Slid ...
- 玩转Web之html+CSS(一)---论坛首页表格的实现
转载请说明出处,小编博客地址:http://blog.csdn.net/u012116457 最近本来想去写一个类似论坛的页面,论坛首页一般都需要一个表格去显示数据,自己简单的写了一下,先上一张图 c ...
- 好代码是管出来的——Git的分支工作流与Pull Request
上一篇文章介绍了常用的版本控制工具以及git的基本用法,从基本用法来看git与其它的版本控制工具好像区别不大,都是对代码新增.提交进行管理,可以查看提交历史.代码差异等功能.但实际上git有一个重量级 ...
- linux.go
func LockFile(file *os.File) error { return syscall.Flock(int(file.Fd()), syscall.LOCK_EX) }
- golang 并发模式笔记
1.并发并不是并行,前者是优先对时间片的抢占,后者是真多核. go中多线程时直接要求并行的方法是: 亦不可滥用,CPU密集型,并发度很高的场景适用. 2.go起的协程 3. function that ...
- SAP GUI个性化设置
大概从GUI730开始,GUI品牌化一直不被默认支持,在GUI设置选项里处于灰色状态,如下图: 不过用户还是可以修改注册表的方式来进行修改,让它可以设置! 首先运行Regedit,在目录:HKEY_L ...