列表

详情


NC220148. 简单的gcd

描述

你有一个长度为n 的数组A,你需要进行m 次操作,一共有如下三种类型的操作方式:

1:增加,将数组中一个数增加一个量;

2:减少,将数组中一个数减少一个量,当减少至0以下时保持为0

3:询问,询问区间l,r之间数的总gcd(不一定是lr,可能是rl);

输入描述

第一行输入两个整数n,m(n,m<=100000)

第二行输入n个整数ai。(ai<1000000)

接下来m行每行输入一个字符串,以及两个整数,字符串‘+’表示增加操作,字符串‘-’表示

减少操作,字符串‘Query’表示询问操作


输出描述

对于每个询问输出一行一个整数表示答案

示例1

输入:

5 6
6 9 10 8 4 
+ 4 1
+ 4 4
+ 1 3
+ 1 4
- 1 1
Query 4 3

输出:

1

原站题解

上次编辑到这里,代码来自缓存 点击恢复默认模板

C++(clang++11) 解法, 执行用时: 182ms, 内存消耗: 4128K, 提交时间: 2021-03-29 10:57:08

#include<iostream>
#include<algorithm>
using namespace std;
enum{maxn=400010};
int tree[maxn],arr[maxn];
int n;
void build(int l=1,int r=n,int p=1){
    if(l>r)return;
    if(l==r) {
        tree[p]=arr[l];
        return ;
    }
    int mid=(l+r)/2;
    build(l,mid,2*p);
    build(mid+1,r,2*p+1);
    tree[p]=__gcd(tree[2*p],tree[2*p+1]);
}
void addpoint(int pos,int k,int l=1,int r=n,int p=1){
    if(l>r)return ;
    if(l==r){
        tree[p]+=k;
        tree[p]=max(tree[p],0);
        return ;
    }
    int mid=(l+r)/2;
    if(pos>mid)addpoint(pos,k,mid+1,r,2*p+1);
    else addpoint(pos,k,l,mid,2*p);
    tree[p]=__gcd(tree[2*p],tree[2*p+1]);
}
int find(int fl,int fr,int l=1,int r=n,int p=1){
    if(l>r) return 0;
    if(fl<=l&&fr>=r) return tree[p];
    int mid=(l+r)/2;
    int a=0,b=0;
    if(fl<=mid) a=find(fl,fr,l,mid,2*p);
    if(fr>mid) b=find(fl,fr,mid+1,r,2*p+1);
    return __gcd(a,b);
}
int m;
char op[20];
int a,b;
int main(){
    //freopen("data.in","r",stdin);
    cin>>n>>m;
    for(int i=1;i<=n;++i) cin>>arr[i];
    build();
    for(int i=0;i<m;++i){
        cin>>op>>a>>b;
        switch(op[0]){
        case '+':
            addpoint(a,b);break;
        case '-':addpoint(a,-b);break;
        case 'Q':
            if(a>b) swap(a,b);
            cout<<find(a,b)<<endl;
        }
    }
}

上一题