F. SUM and REPLACE
time limit per test
2 seconds
memory limit per test
256 megabytes
input
standard input
output
standard output
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:
- REPLACE l r — for every replace ai with D(ai);
- SUM l r — calculate .
Print the answer for each SUM query.
Input
The first line contains two integers n and m (1 ≤ n, m ≤ 3·105) — the number of elements in the array and the number of queries to process, respectively.
The second line contains n integers a1, a2, ..., an (1 ≤ ai ≤ 106) — the elements of the array.
Then m lines follow, each containing 3 integers ti, li, ri denoting i-th query. If ti = 1, then i-th query is REPLACE li ri, otherwise it's SUMli ri (1 ≤ ti ≤ 2, 1 ≤ li ≤ ri ≤ n).
There is at least one SUM query.
Output
For each SUM query print the answer to it.
Example
input
Copy
7 6
6 4 1 10 3 2 4
2 1 7
2 4 5
1 3 5
2 4 4
1 5 7
2 1 7
output
Copy
30
13
4
22
线段树。开始求整除的个数 要用dp。先求出,其某个因子。
import java.util.*;
import java.io.*;
public class Main {
public static void main(String args[]) {new Main().run();}
FastReader in = new FastReader();
PrintWriter out = new PrintWriter(System.out);
void run(){
work();
out.flush();
}
long mod=998244353;
long gcd(long a,long b) {
return b==0?a:gcd(b,a%b);
}
int[] dp;
void work() {
int[] rec=new int[1000001];
Arrays.fill(rec,1);
for(int i=2;i*i<=1000000;i++) {
if(rec[i]==1) {
for(int j=i;j*i<=1000000;j++) {
rec[i*j]=i;
}
}
}
dp=new int[1000001];
dp[1]=1;
for(int i=2;i<=1000000;i++) {
int d=rec[i];
if(d==1)dp[i]=2;
else {
int c=0;
int num=i;
while(num%d==0) {
c++;
num/=d;
}
dp[i]=dp[num]*(c+1);
}
}
int n=in.nextInt(),m=in.nextInt();
int[] A=new int[n];
for(int i=0;i<n;i++)A[i]=in.nextInt();
Node root=new Node();
for(int i=0;i<n;i++) {
insert(root,A[i],i,0,n-1);
}
for(int i=0;i<m;i++) {
int type=in.nextInt();
if(type==1) {
update(root,in.nextInt()-1,in.nextInt()-1,0,n-1);
}else {
out.println(query(root,in.nextInt()-1,in.nextInt()-1,0,n-1));
}
}
}
private long query(Node node, int s, int e, int l, int r) {
if(l>=s&&r<=e) {
return node.sum;
}
Node lnode=getLnode(node);
Node rnode=getRnode(node);
long ret=0;
int m=(l+r)/2;
if(m>=s) {
ret+=query(lnode,s,e,l,m);
}
if(m<e) {
ret+=query(rnode,s,e,m+1,r);
}
return ret;
}
private void update(Node node,int s, int e,int l,int r) {
if(l==r) {
node.sum=dp[(int)node.sum];
if(dp[(int)node.sum]==node.sum)node.cnt--;
return;
}
Node lnode=getLnode(node);
Node rnode=getRnode(node);
int m=(l+r)/2;
if(m>=s&&lnode.cnt>0) {
update(lnode,s,e,l,m);
}
if(m<e&&rnode.cnt>0) {
update(rnode,s,e,m+1,r);
}
node.sum=lnode.sum+rnode.sum;
node.cnt=lnode.cnt+rnode.cnt;
}
private void insert(Node node, long v,int idx, int l, int r) {
if(l==r) {
node.sum=v;
if(dp[(int)v]!=v)node.cnt++;
return;
}
int m=(l+r)/2;
Node lnode=getLnode(node);
Node rnode=getRnode(node);
if(idx<=m) {
insert(lnode,v,idx,l,m);
}else {
insert(rnode,v,idx,m+1,r);
}
node.cnt=lnode.cnt+rnode.cnt;
node.sum=lnode.sum+rnode.sum;
}
private Node getRnode(Node node) {
if(node.rnode==null) node.rnode=new Node();
return node.rnode;
}
private Node getLnode(Node node) {
if(node.lnode==null) node.lnode=new Node();
return node.lnode;
}
class Node{
Node lnode,rnode;
int cnt;
long sum;
}
}
class FastReader
{
BufferedReader br;
StringTokenizer st;
public FastReader()
{
br=new BufferedReader(new InputStreamReader(System.in));
}
public String next()
{
if(st==null || !st.hasMoreElements())
{
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
public int nextInt()
{
return Integer.parseInt(next());
}
public long nextLong()
{
return Long.parseLong(next());
}
}
预处理因数个数的时候 想复杂了。以下较简单方法。速度慢了点(951ms,上面701ms)。
import java.util.*;
import java.io.*;
public class Main {
public static void main(String args[]) {new Main().run();}
FastReader in = new FastReader();
PrintWriter out = new PrintWriter(System.out);
void run(){
work();
out.flush();
}
long mod=998244353;
long gcd(long a,long b) {
return b==0?a:gcd(b,a%b);
}
int[] dp;
void work() {
dp=new int[1000001];
for(int i=1;i<=1000000;i++) {
for(int j=i;j<=1000000;j+=i) {
dp[j]++;
}
}
int n=in.nextInt(),m=in.nextInt();
int[] A=new int[n];
for(int i=0;i<n;i++)A[i]=in.nextInt();
Node root=new Node();
for(int i=0;i<n;i++) {
insert(root,A[i],i,0,n-1);
}
for(int i=0;i<m;i++) {
int type=in.nextInt();
if(type==1) {
update(root,in.nextInt()-1,in.nextInt()-1,0,n-1);
}else {
out.println(query(root,in.nextInt()-1,in.nextInt()-1,0,n-1));
}
}
}
private long query(Node node, int s, int e, int l, int r) {
if(l>=s&&r<=e) {
return node.sum;
}
Node lnode=getLnode(node);
Node rnode=getRnode(node);
long ret=0;
int m=(l+r)/2;
if(m>=s) {
ret+=query(lnode,s,e,l,m);
}
if(m<e) {
ret+=query(rnode,s,e,m+1,r);
}
return ret;
}
private void update(Node node,int s, int e,int l,int r) {
if(l==r) {
node.sum=dp[(int)node.sum];
if(dp[(int)node.sum]==node.sum)node.cnt--;
return;
}
Node lnode=getLnode(node);
Node rnode=getRnode(node);
int m=(l+r)/2;
if(m>=s&&lnode.cnt>0) {
update(lnode,s,e,l,m);
}
if(m<e&&rnode.cnt>0) {
update(rnode,s,e,m+1,r);
}
node.sum=lnode.sum+rnode.sum;
node.cnt=lnode.cnt+rnode.cnt;
}
private void insert(Node node, long v,int idx, int l, int r) {
if(l==r) {
node.sum=v;
if(dp[(int)v]!=v)node.cnt++;
return;
}
int m=(l+r)/2;
Node lnode=getLnode(node);
Node rnode=getRnode(node);
if(idx<=m) {
insert(lnode,v,idx,l,m);
}else {
insert(rnode,v,idx,m+1,r);
}
node.cnt=lnode.cnt+rnode.cnt;
node.sum=lnode.sum+rnode.sum;
}
private Node getRnode(Node node) {
if(node.rnode==null) node.rnode=new Node();
return node.rnode;
}
private Node getLnode(Node node) {
if(node.lnode==null) node.lnode=new Node();
return node.lnode;
}
class Node{
Node lnode,rnode;
int cnt;
long sum;
}
}
class FastReader
{
BufferedReader br;
StringTokenizer st;
public FastReader()
{
br=new BufferedReader(new InputStreamReader(System.in));
}
public String next()
{
if(st==null || !st.hasMoreElements())
{
try {
st = new StringTokenizer(br.readLine());
} catch (IOException e) {
e.printStackTrace();
}
}
return st.nextToken();
}
public int nextInt()
{
return Integer.parseInt(next());
}
public long nextLong()
{
return Long.parseLong(next());
}
}