題目:c++
Let D(x) be the number of positive divisors of a positive integer x. For example, D(2) = 2 (2 is divisible by 1 and 2), D(6) = 4 (6 is divisible by 1, 2, 3 and 6).數組
You are given an array a of n integers. You have to process two types of queries:ide
Print the answer for each SUM query.spa
分析:code
咱們考慮到每一個數能夠進行操做的數量不會不少,且D(1)=1,D(2)=2.orm
咱們只須要暴力修改就好了,而後用樹狀數組求和.blog
如何優雅的暴力?get
也就是說如何快速找出區間[l,r]內知足ai>2的i值.考慮用set維護還能夠操做的下標的點,每次用lb,ub去找.暴力修改.it
另外篩1-1e6中每一個數的因子個數的方法須要注意.event
1 #include<bits/stdc++.h> 2 using namespace std; 3 typedef long long LL; 4 const int MAXN=3e5+7; 5 int N,M; 6 LL a[MAXN],val[MAXN]; 7 int D[1000001]; 8 inline int lowbit(int i){ 9 return i&-i; 10 } 11 LL sum(int x){ 12 LL res=0; 13 while(x){ 14 res+=a[x]; 15 x-=lowbit(x); 16 } 17 return res; 18 } 19 void add(int i,int x){ 20 while(i<=N){ 21 a[i]+=x; 22 i+=lowbit(i); 23 } 24 } 25 int getD(long long x){ 26 return D[x]; 27 } 28 int main(){ 29 for(int i=1;i<=1000000;++i){ 30 for(int j=i;j<=1000000;j+=i){ 31 D[j]++; 32 } 33 } 34 scanf("%d%d",&N,&M); 35 set<int>st; 36 for(int i=1;i<=N;++i){ 37 scanf("%I64d",&val[i]); 38 if(val[i]>2)st.insert(i); 39 add(i,val[i]); 40 } 41 while(M--){ 42 int t,l,r;scanf("%d%d%d",&t,&l,&r); 43 if(t==1){ 44 auto first=st.lower_bound(l); 45 auto last=st.upper_bound(r); 46 queue<int>q; 47 while(first!=last){ 48 int i=*first; 49 int x=getD(val[i]); 50 add(i,x-val[i]); 51 val[i]=x; 52 if(x<=2)q.push(i); 53 first++; 54 } 55 while(!q.empty()){ 56 int now=q.front();q.pop(); 57 st.erase(now); 58 } 59 }else{ 60 printf("%I64d\n",sum(r)-sum(l-1)); 61 } 62 } 63 return 0; 64 }