Luogu1483
Update
许多人得了 \(60\) 分,而不解原因。\(60\) 分的看过来。
其实是因为出题人不讲武德,造假数据,说说是 \(1\le j\le n\),实际上有
\(j=0\) 的情况,而这对于有的算法是毁灭性的打击。
思路
根号分治。
设阈值 \(\mathtt{lim}\) ,修改操作在阈值以上时,暴力修是
\(O(\frac n{\mathtt{lim}})\) 的;否则打一个懒惰标记,是 \(O(1)\) 的。
查询时可以乱搞,统计不超过阈值的懒惰标记中对其有影响的部分,再加上其本身已计部分,即可,复杂度 \(O(\mathtt{lim})\);注意特判 \(j=0\)。
取 \(\mathtt{lim}=\sqrt n\) 时,单次操作复杂度是最坏 \(O(\sqrt n)\) 的。
其实可以更好,但请参阅其它题解,这里就不多介绍了。
Code
#include <stdio.h>
typedef long long llt;
typedef unsigned uint;typedef unsigned long long ullt;
typedef bool bol;typedef char chr;typedef void voi;
typedef double dbl;
template<typename T>bol _max(T&a,T b){return(a<b)?a=b,true:false;}
template<typename T>bol _min(T&a,T b){return(b<a)?a=b,true:false;}
const uint lim=1000;
llt Lazy[1005],A[1000005];
int main()
{
uint n,m,op,x;llt y;scanf("%u%u",&n,&m);
for(uint i=1;i<=n;i++)scanf("%lld",A+i);
for(uint i=1;i<=m;i++)
{
scanf("%u%u",&op,&x);
if(op==1)
{
scanf("%lld",&y);
if(x<=lim)Lazy[x]+=y;
else for(uint j=x;j<=n;j+=x)A[j]+=y;
}
else
{
if(!x)
{
puts("0");
continue;
}
llt ans=A[x];
for(uint j=1;j<=lim;j++)if(!(x%j))ans+=Lazy[j];
printf("%lld\n",ans);
}
}
return 0;
}
本文来自博客园,作者:myee,转载请注明原文链接:https://www.cnblogs.com/myee/p/Luogu-solution-p1483.html