PROBLEM LINK:
Author: agarwal_keshav
Tester: dragno99
Editorialist: agarwal_keshav
DIFFICULTY:
MEDIUM-HARD
PROBLEM:
Given an array a consisting of n numbers and we can ask you 2 type of query-
-
Type 1- Given an integer i and v (0 \leq i \leq n−1) Change the value of the a_i with v.
-
Type 2 - you are given two integer l and r such that (0≤l≤r≤n−1) Print the number of distinct prime factors in (a_l + a_{l+1} + ... + a_r) which are not the factors of any a_t where l≤t≤r.
Prerequisites:
- segment tree
EXPLANATION:
well we can use segment tree to update the elements in array as well as to find the sum in range from l to r. we can also use the sieve and shortest prime factor method to find the prime factors of any number but now the question is how we will check that a particular prime factor of sum is also a factor of any array element indexed from l to r or not. to solve this we can do one thing, corresponding to prime factor x we will store all the array index i such that x is a factor of a_i and then to check should we count the prime factor let’s say x of sum in range l to r for our answer or not we will apply binary search over set[x] and check if any element in the range l to r present in our set or not.
SOLUTIONS:
Setter's Solution
#include <bits/stdc++.h>
using namespace std;
#define ll long long int
#define nl cout<<"\n";
#define fix(f,n) cout<<fixed<<setprecision(n)<<f
const int mod = 1e9+7;
template<typename ...T>
void debug(T&&... args){ ((cerr << args << " "), ...);cerr<<"\n";}
ll gcd(ll a,ll b){ return a?gcd(b%a,a):b; }
ll minv(ll a,ll b){ return a<b?a:b;}
ll maxv(ll a,ll b){ return a>b?a:b;}
void swapv(ll &a,ll &b){a=a+b;b=a-b;a=a-b;}
ll power(ll a, ll b, ll m=mod){
if(a==0 || b==1) return a;
if(b==0) return 1;ll ans=1;
while(b>=1){ if(b&1){b--;ans = (ans*a) % m;}a = (a*a)% m;b = b>>1;}return ans;
}
ll logv(ll x){ll ans =-1;while(x){x = x>>1;ans++;}return ans;}
ll inv(ll a,ll m){return power(a,m-2,m);}
const ll mxSize = 1e6 + 5;
ll spf[mxSize];
ll primes[60];
void sieve(){
for(int i=1;i<mxSize;i++) spf[i] = i;
int k=0;
for(int i=2;i*i<mxSize;i++){
if(spf[i]==i){
if(k<60){
primes[k] = i;
k++;
}
for(int j=i*i;j<mxSize;j+=i){
if(spf[j]==j) spf[j] = i;
}
}
}
}
ll findNumOfPrime(ll num,unordered_map<ll,set<ll>> &mp,ll l,ll r){
ll count = 0;
while(num > 1){
ll fact = spf[num];
auto it = mp[fact].lower_bound(l);
if((it==mp[fact].end()) || (*it > r)){
count++;
}
while(spf[num]==fact){
num = num/fact;
}
}
return count;
}
class segTree{
public:
vector<ll> vec;
ll size;
segTree(int n){
size = n;
vec.resize(4*n);
}
void insert(int l,int r,int index,ll val1,ll i){
if((l>i) || (r<i)) return;
if(l==r){
vec[index] = val1;
return;
}
int mid = l + (r - l)/2;
int child1 = 2*index + 1;
int child2 = 2*index + 2;
insert(l,mid,child1,val1,i);
insert(mid+1,r,child2,val1,i);
vec[index] = vec[child1] + vec[child2];
}
void insert(ll val,ll i){
insert(0,size-1,0,val,i);
}
ll query(ll lrange, ll rrange,ll left,ll right,ll index){
if((rrange < left) || (lrange > right)){
return 0;
}
if((lrange >= left) && (rrange <= right)){
return vec[index];
}
ll mid = lrange + (rrange - lrange)/2;
return query(lrange,mid,left,right,2*index+1) + query(mid + 1,rrange,left,right,2*index+ 2);
}
ll query(ll l,ll r){
return query(0,size-1,l,r,0);
}
};
void addPrime(unordered_map<ll,set<ll>> &mp,ll num,ll index){
while(num > 1){
ll fact = spf[num];
mp[fact].insert(index);
while(spf[num]==fact){
num = num/fact;
}
}
}
void removePrime(unordered_map<ll,set<ll>> &mp,ll num,ll index){
while(num > 1){
ll fact = spf[num];
mp[fact].erase(index);
while(spf[num]==fact){
num = num/fact;
}
}
}
int main() {
ios_base::sync_with_stdio(false);
cin.tie(NULL);
#ifndef ONLINE_JUDGE
freopen("input.txt", "r", stdin);
freopen("output.txt", "w", stdout);
freopen("error.txt","w",stderr);
#endif
sieve();
ll n,q;
cin>>n>>q;
ll a[n];
segTree tree(n);
unordered_map<ll,set<ll>> mp;
for(int i=0;i<n;i++){
ll x;cin>>x;
a[i] = x;
addPrime(mp,a[i],i);
tree.insert(x,i);
}
while(q--){
int type;
cin>>type;
if(type==1){
ll i,v;
cin>>i>>v;
removePrime(mp,a[i],i);
a[i] = v;
addPrime(mp,a[i],i);
tree.insert(v,i);
}else{
ll l,r;
cin>>l>>r;
ll sum;
sum = tree.query(l,r);
cout<<findNumOfPrime(sum,mp,l,r);nl;
}
}
return 0;
}
Tester's Solution
#include "bits/stdc++.h"
using namespace std;
template<typename T>
class SegTree{
private:
void update(int id,const int pos,const T val,int s,int e){
if(s>e) return;
if(s==e){ // base case
v[id] = val;
return;
}
int mid = (s+e)/2;
if(pos<=mid) update(2*id,pos,val,s,mid);
else update(2*id+1,pos,val,mid+1,e);
v[id] = join(v[2*id],v[2*id+1]);
return;
}
T query(int id,const int l,const int r,const int s,const int e){
if(s>e || r<s || l>e) return dummy;
else if(l<=s && e<=r) return v[id];
else return join(query(2*id,l,r,s,(s+e)/2),query(2*id+1,l,r,(s+e)/2+1,e));
}
public:
int n;
vector<T> v;
T dummy; // dummy node
function<T(const T&,const T&)> join;
SegTree(int n,T dummy,function<T(const T&,const T&)> join):n(n), join(join), dummy(dummy), v(4*n,dummy){}
void update(const int pos,const T val){ update(1,pos,val,1,n); }
T query(const int l,const int r){ return query(1,l,r,1,n); }
};
const int N = 1e6 + 10;
int spf[N];
unordered_map<int,set<int>> m;
void gen(){
for(int i=0;i<N;i++) spf[i] = i;
for(int i=2;i<N;i++){
if(spf[i] == i){
for(int j=i;j<N;j+=i){
if(spf[j] == j){
spf[j] = i;
}
}
}
}
}
vector<int> getPfac(int x){
vector<int> ans;
while(x > 1){
int f = spf[x];
ans.push_back(f);
while(x % f == 0){
x/=f;
}
}
return ans;
}
void addInMap(int x,int id){
auto curr = getPfac(x);
for(auto &p: curr){
m[p].insert(id);
}
}
void removeFromMap(int x,int id){
auto curr = getPfac(x);
for(auto &p: curr){
m[p].erase(id);
if(m[p].size() == 0){
m.erase(p);
}
}
}
int getAns(int sum , int l,int r){
int ans = 0;
auto primeFac = getPfac(sum);
for(auto &i: primeFac){
if(m.count(i)){
auto it = m[i].lower_bound(l);
if(it == m[i].end() || *it > r){
ans++;
}
}
else ans++;
}
return ans;
}
void __sol(){
int n,q; cin >> n >> q;
SegTree<long long> s(n , 0LL , [&](long long x,long long y){
return x + y;
});
vector<int> v(n);
for(int i=0;i<n;i++){
cin >> v[i];
addInMap(v[i] , i);
s.update(i+1 , v[i]);
}
while(q--){
int type; cin >> type;
if(type == 1){
int i,x; cin >> i >> x;
removeFromMap(v[i] , i);
v[i] = x;
addInMap(v[i] , i);
s.update(i + 1, x);
}
else{
int l,r; cin >> l >> r;
cout << getAns( s.query(l + 1 , r + 1) , l , r) << "\n";
}
}
return;
}
int main(){
gen();
int tc=1; // cin >> tc;
while(tc--) __sol();
return 0;
}