LG5278 수학 천재 ⑨와 연산 순서 및 CH4302 간격 GCD

⑨ 수학 천재 연산 시퀀스

길이 N, 다음과 같은 두 가지 작업을 지원할 필요가 일련의 감안할 때 :

  1. 수정의 단일 지점
  2. 심문 영역 내의 각각 상승 · 여부 연산 시퀀스 번호

N ≤ 100000 200000 M ≤ 데이터는 10 ≤ 9

문제 해결

산술 시리즈로 부의 개수가 명확 구간에서 가장 값이 필요한지 여부를 알 수있을 (즉, 제 1 열 및 마지막 엔트리 수) 상기 계산 된 오차에 대응.

산술 시리즈 간격으로 음의 수는 필요에 다음을 만족하는 경우 :

  1. 제로 관용;
  2. 공차가 0이 아닌 비 동일한 엘리먼트 내의 열의 수, 인접하는 차분 값 GCD의 공차.

따라서 유지 보수가 요구되는 최소 간격이 최대 값과 동일한 전구체 분별 칼럼 GCD 구간 수와 각 요소의 위치 사이의 차이. 각 요소는 전구체 위치지도 세트의 동일한 번호가 설정 될 수 유지.

당신은 잘못 될 수 있을까?

유지 구간 최대 값, 최소값, 그리고, 자 승합 후 판정.

라인에 출시 산술 진행 광장과 공식 폭력.

어떤 사람들은 카드를 교환 할 수 있다고?

typedef __int128 LL;

CO int N=300000+10;
struct node{
    int min,max;
    LL sum1,sum2;
};
node operator+(CO node&a,CO node&b){
    return (node){
        min(a.min,b.min),max(a.max,b.max),
        a.sum1+b.sum1,a.sum2+b.sum2
    };
}

node tree[4*N];
#define lc (x<<1)
#define rc (x<<1|1)
void build(int x,int l,int r){
    if(l==r){
        int v=read<int>();
        tree[x]=(node){v,v,v,(LL)v*v};
        return;
    }
    int mid=(l+r)>>1;
    build(lc,l,mid),build(rc,mid+1,r);
    tree[x]=tree[lc]+tree[rc];
}
void change(int x,int l,int r,int p,int v){
    if(l==r){
        tree[x]=(node){v,v,v,(LL)v*v};
        return;
    }
    int mid=(l+r)>>1;
    if(p<=mid) change(lc,l,mid,p,v);
    else change(rc,mid+1,r,p,v);
    tree[x]=tree[lc]+tree[rc];
}
node query(int x,int l,int r,int ql,int qr){
    if(ql<=l and r<=qr) return tree[x];
    int mid=(l+r)>>1;
    if(qr<=mid) return query(lc,l,mid,ql,qr);
    if(ql>mid) return query(rc,mid+1,r,ql,qr);
    return query(lc,l,mid,ql,qr)+query(rc,mid+1,r,ql,qr);
}

int main(){
    int n=read<int>(),m=read<int>();
    build(1,1,n);
    int yes=0;
    while(m--){
        if(read<int>()==1){
            int p=read<int>()^yes,v=read<int>()^yes;
            change(1,1,n,p,v);
        }
        else{
            int l=read<int>()^yes,r=read<int>()^yes,k=read<int>()^yes;
            bool valid=1;
            node x=query(1,1,n,l,r);
            if(x.max-x.min!=(LL)(r-l)*k) valid=0;
            if(x.sum1!=(LL)(x.min+x.max)*(r-l+1)/2) valid=0;
            if(x.sum2!=(LL)(r-l+1)*x.min*x.min+(LL)2*k*(r-l)*(r-l+1)/2*x.min
            +(LL)k*k*(r-l)*(r-l+1)*(2*r-2*l+1)/6) valid=0;
            puts(valid?"Yes":"No"),yes+=valid;
        }
    }
    return 0;
}

기술

길이 n은 일련의 주어와 M 지침 (N≤5 * 10 ^ 5, M은 <= 10 ^ 5), 각 명령어는 다음 중 하나 일 수있다 :
"C LRD을"A는 나타내고 [1], A [L + 1], ..., A [R]을 더한 D이다.
"Q의 LR"질의 A를 나타내는 [1], A [L + 1], ..., A [R] 최대 공약수 (GCD).

입력 형식

두 정수의 첫 번째 라인은 N, M은 정수 N 번째 주제에 설명 된 각각의 명령 형식의 다음 행에 도시 된 바와 같이, AI, M 로우.

출력 형식

각 질문의 경우, 출력 정수 대답.

샘플 입력

5 5 
1 3 5 7 9 
Q 1~5 
C 1 5 1 
Q 1-5 
C 3 3 6 
Q 2~4

샘플 출력

1 
2 
4

데이터 범위 및 규칙

  • N은 M≤2 * 10 ^ 5 L <= R, 데이터의 개수는 시간 순서하게는 62-1 ^ 2 이하의 양의 정수되도록.

분석

은 "감소 기법"\는 (GCD은 (X는, Y는 Z가) = GCD (X, YX, ZY) \) 때문에
gcd_ {I = L \ [\ GCD \} ^ RN A [L] = ( 이 [L] \ gcd_ {
I = 1 + 1} ^ RN (a [I] -A [I-1])) \] 따라서, 차이 시퀀스 세그먼트 트리 GCD 선분 트리 변형 부분의 한 지점을 유지할 쿼리 후 새로운 배열을 유지하는 트리 차이 시퀀스 원래 단일 포인트 조회 시퀀스의주기 값을 수정한다.

시간 복잡도 \ (O (M \ 로그 N ) \)

co int N=5e5+1;
int n,m;
ll a[N],b[N],c[N];
#define lowbit(i) (i&-i)
void add(int p,ll v){
    for(;p<=n;p+=lowbit(p)) c[p]+=v;
}
ll ask(int p){
    ll re=0;
    for(;p;p-=lowbit(p)) re+=c[p];
    return re;
}
ll s[N*4];
ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;}
#define lc (x<<1)
#define rc (x<<1|1)
void build(int x,int l,int r){
    if(l==r) return s[x]=b[l],void();
    int mid=l+r>>1;
    build(lc,l,mid),build(rc,mid+1,r);
    s[x]=gcd(s[lc],s[rc]);
}
void change(int x,int l,int r,int p){
    if(l==r) return s[x]=b[l],void();
    int mid=l+r>>1;
    if(p<=mid) change(lc,l,mid,p);
    else change(rc,mid+1,r,p);
    s[x]=gcd(s[lc],s[rc]);
}
ll query(int x,int l,int r,int ql,int qr){
    if(ql>qr) return 0;
    if(ql<=l&&r<=qr) return s[x];
    int mid=l+r>>1;
    if(qr<=mid) return query(lc,l,mid,ql,qr);
    if(ql>mid) return query(rc,mid+1,r,ql,qr);
    return gcd(query(lc,l,mid,ql,qr),query(rc,mid+1,r,ql,qr));
}
int main(){
//  freopen("CH4302.in","r",stdin),freopen("CH4302.out","w",stdout);
    read(n),read(m);
    for(int i=1;i<=n;++i) b[i]=read(a[i])-a[i-1];
    build(1,1,n); // edit 1: reserve for changing b[1]
    for(int l,r;m--;){
        static char op[2];
        scanf("%s",op),read(l),read(r);
        if(op[0]=='C'){
            ll d=read<ll>(); // edit 2
            b[l]+=d,change(1,1,n,l),add(l,d);
            if(r+1<=n) b[r+1]-=d,change(1,1,n,r+1),add(r+1,-d);
        }
        else printf("%lld\n",llabs(gcd(a[l]+ask(l),query(1,1,n,l+1,r))));
    }
    return 0;
}

추천

출처www.cnblogs.com/autoint/p/11738331.html