This submission is migrated from previous version of oj.uz, which used different machine for grading. This submission may have different result if resubmitted.
using namespace std;
#include <iostream>
#include <cstring>
#define MAXN 131072
#define MAXL 31
long long gcd(long long a,long long b) {
while(b) {
a %= b;
swap(a,b);
}
return a;
}
// Tournament Tree
struct node {
int preS,sufS,preI[MAXL],preI2[MAXL],sufI[MAXL],sufI2[MAXL],index,pre[MAXL],suf[MAXL],ans;
node(int i,long long v) {
memset(pre,0,sizeof(pre));
memset(suf,0,sizeof(suf));
pre[0] = suf[0] = v;
preI[0] = sufI[0] = preI2[0] = sufI2[0] = index = i;
preS = sufS = 1;
ans = 1;
if(v == 1) ans = 0;
}
node() {
preS = 0;
sufS = 0;
}
};
node nodes[2 * MAXN];
// a is in front of b
node combine(node& a,node& b,bool debug = false) {
node res;
res.ans = a.ans + b.ans;
res.preS = res.sufS = 0;
res.index = a.index;
if(debug) cout << "done " << b.index << " " << b.ans << " " << endl;
// Prefix
for(int i = 0;i < a.preS;++i) {
res.pre[res.preS] = a.pre[i];
res.preI[res.preS] = a.preI[i];
res.preI2[res.preS++] = a.preI2[i];
}
for(int i = 0;i < b.preS;++i) {
if(gcd(b.pre[i],res.pre[res.preS - 1]) != res.pre[res.preS - 1]) {
res.pre[res.preS] = gcd(b.pre[i],res.pre[res.preS - 1]);
res.preI[res.preS] = b.preI[i];
res.preI2[res.preS++] = b.preI2[i];
}else{
if(debug) cout << "hi " << b.preI2[i] << endl;
res.preI2[res.preS - 1] = b.preI2[i];
}
}
// Suffix
for(int i = 0;i < b.sufS;++i) {
res.suf[res.sufS] = b.suf[i];
res.sufI[res.sufS] = b.sufI[i];
res.sufI2[res.sufS++] = b.sufI2[i];
}
for(int i = 0;i < a.sufS;++i) {
if(gcd(a.suf[i],res.suf[res.sufS - 1]) != res.suf[res.sufS - 1]) {
res.suf[res.sufS] = gcd(a.suf[i],res.suf[res.sufS - 1]);
res.sufI[res.sufS] = a.sufI[i];
res.sufI[res.sufS++] = a.sufI2[i];
}else{
res.sufI2[res.sufS - 1] = a.sufI2[i];
}
}
// Count new interesting subarrays
int ptr = 0;
for(int i = b.preS - 1;i >= 0;--i) {
while(ptr < a.sufS && gcd(b.pre[i],a.suf[ptr]) != 1) {
ptr++;
}
ptr--;
// if(debug) cout << "pointer " << ptr << " " << b.index << " " << a.sufI2[ptr] << " " << (b.preI2[ptr] - b.preI[ptr] + 1) << endl;
if(ptr >= 0) res.ans += 1ll * (b.index - a.sufI2[ptr]) * (b.preI2[ptr] - b.preI[ptr] + 1);
}
return res;
}
void update(int x,long long v) {
x += MAXN;
nodes[x] = node(x - MAXN,v);
// cout << "hi " << x << endl;
for(;x >>= 1;) {
nodes[x] = combine(nodes[x << 1],nodes[x << 1 | 1]);
}
}
long long query(int l,int r) {
node resl(-1,1);
node resr(-1,1);
r++;
for(l += MAXN,r += MAXN;l < r;l >>= 1,r >>= 1) {
// cout << l << " " << r << endl;
if(l & 1) {
if(resl.index == -1) {
resl = nodes[l++];
}else{
resl = combine(resl,nodes[l++],false);
}
}
if(r & 1) {
if(resr.index == -1) {
resr = nodes[--r];
}else{
resr = combine(nodes[--r],resr,false);
}
}
}
if(resl.index == -1) return resr.ans;
if(resr.index == -1) return resl.ans;
return combine(resl,resr,false).ans;
}
int N,Q;
int main() {
cin >> N >> Q;
for(int i = 0;i < N;++i) {
long long cur;
cin >> cur;
update(i,cur);
}
for(int i = N;i < MAXN;++i) {
update(i,1);
}
// cout << nodes[MAXN / 4].pre[0] << " " << nodes[MAXN / 4].preI[0] << " " << nodes[MAXN / 4].preI2[0] << endl;
for(int i = 0;i < Q;++i) {
long long a,b,c;
cin >> a >> b >> c;
b--;
if(a == 1) {
update(b,c);
}else{
c--;
cout << query(b,c) << endl;
}
}
return 0;
}
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |
# | Verdict | Execution time | Memory | Grader output |
---|
Fetching results... |