和花神游历各国有一点像的地方就是都到某一状态后就可以不修改了。当当前值为1/2时就不用修改了。
对于预处理每个数的因子数,我只会(n^2)的,但显然不行,后来我突然想到一个渐进于(O(nlnn))的,如代码(后来发现是我太菜想不到,别人都是这的写的)
#include <iostream>
#include <cstdio>
#include <cctype>
#include <cstring>
#define mid (l+r>>1)
#define ls (cur<<1)
#define rs (cur<<1|1)
using namespace std;
const int N=2000005;
typedef long long ll;
int rd() {
int x=0;char ch=getchar();
while(!isdigit(ch)) ch=getchar();
while(isdigit(ch)) x=x*10+ch-'0',ch=getchar();
return x;
}
struct Segtree{int l,r;ll sum;bool flag;}t[N<<2];
int n,m,d[N];
void pushup(int cur) {
t[cur].sum=t[ls].sum+t[rs].sum;
t[cur].flag=t[ls].flag&t[rs].flag;
}
void build(int cur,int l,int r) {
t[cur].l=l,t[cur].r=r;
if(l==r) {t[cur].sum=rd();if(t[cur].sum==1||t[cur].sum==2) t[cur].flag=1;return;}
build(ls,l,mid);
build(rs,mid+1,r);
pushup(cur);
}
void update(int L,int R,int cur) {
if(t[cur].flag) return;
int l=t[cur].l,r=t[cur].r;
if(l==r) {t[cur].sum=d[t[cur].sum];if(t[cur].sum==1||t[cur].sum==2) t[cur].flag=1;return;}
if(mid<L) update(L,R,rs);
else if(R<=mid) update(L,R,ls);
else update(L,mid,ls),update(mid+1,R,rs);
pushup(cur);
}
ll query(int L,int R,int cur) {
int l=t[cur].l,r=t[cur].r;
if(L<=l&&r<=R) {return t[cur].sum;}
if(mid<L) return query(L,R,rs);
else if(R<=mid) return query(L,R,ls);
else return query(L,mid,ls)+query(mid+1,R,rs);
}
int main() {
n=rd(),m=rd();
for(int i=1;i<=1e6;i++)
for(int j=i;j<=1e6;j+=i)
d[j]++;
int opt,l,r;
build(1,1,n);
while(m--) {
opt=rd();l=rd();r=rd();
if(opt==1) update(l,r,1);
else printf("%lld
",query(l,r,1));
}
// for(int i=1;i<=100;i++) printf("%d ",d[i]);
}