zoukankan      html  css  js  c++  java
  • 区间最大公约数

    AcWing

    题意:维护两种操作,区间增加和查询区间最大公约数.

    分析:借助于求最大公约数的方法之一:更相减损术,(gcd(a,b)=gcd(a,b-a)),推广到任意个都成立,所以可以维护原数组(A)的差分数组(B),用线段树维护这个差分数组的最大公约数.

    对于一个区间增加操作,就只要让(B[l]+=val,B[r-1]-=val).即单点修改操作.

    对于一次查询,就等于求出(gcd(A[l],query(1,l+1,r))).发现我们还要维护(A)数组的值,这个可以简单用一个树状数组来维护.

    本题细节较多,(long) (long)是最基本的,然后(gcd)如果是负数要变成正数,如果修改操作中的(r+1>n)就跳过.

    #include<iostream>
    #include<cstdio>
    #include<algorithm>
    #include<cstring>
    #include<cmath>
    #include<queue>
    #include<map>
    #include<set>
    #define ll long long
    using namespace std;
    inline ll read(){
        ll x=0,o=1;char ch=getchar();
        while(ch!='-'&&(ch<'0'||ch>'9'))ch=getchar();
        if(ch=='-')o=-1,ch=getchar();
        while(ch>='0'&&ch<='9')x=x*10+ch-'0',ch=getchar();
        return x*o;
    }
    const int N=500005;
    ll n,m,a[N],b[N],c[N];
    struct XD_Tree{ll l,r,data;}t[N<<2];
    inline ll gcd(ll a,ll b){
    	if(!b)return a;
    	return gcd(b,a%b);
    }
    inline void build(int p,ll l,ll r){
    	t[p].l=l;t[p].r=r;
    	if(l==r){t[p].data=b[l];return;}
    	ll mid=(l+r)>>1;
    	build(p<<1,l,mid);build(p<<1|1,mid+1,r);
    	t[p].data=gcd(t[p<<1].data,t[p<<1|1].data);
    }
    inline void change(int p,ll pos,ll v){
    	int l=t[p].l,r=t[p].r;
    	if(l==r){t[p].data+=v;return;}
    	int mid=(l+r)>>1;
    	if(pos<=mid)change(p<<1,pos,v);
    	else change(p<<1|1,pos,v);
    	t[p].data=gcd(t[p<<1].data,t[p<<1|1].data);
    }
    inline ll query(int p,ll ql,ll qr){
    	int l=t[p].l,r=t[p].r;
    	if(ql<=l&&qr>=r)return abs(t[p].data);	
    	ll mid=(l+r)>>1,gcdl=0,gcdr=0;
    	if(ql<=mid)gcdl=query(p<<1,ql,qr);	
    	if(qr>mid)gcdr=query(p<<1|1,ql,qr);
    	return abs(gcd(gcdl,gcdr));
    }
    inline ll lowbit(ll x){return x&-x;}
    inline void add(ll x,ll y){for(;x<=n;x+=lowbit(x))c[x]+=y;}
    inline ll ask(ll x){ll cnt=0;for(;x;x-=lowbit(x))cnt+=c[x];return cnt;}
    int main(){
    	n=read();m=read();for(int i=1;i<=n;++i)a[i]=read();
    	for(int i=1;i<=n;++i)b[i]=a[i]-a[i-1];build(1,1,n);
    	while(m--){
    		char ch;cin>>ch;
    		if(ch=='C'){
    			ll l,r,val;l=read();r=read();val=read();
    			add(l,val);if(r+1<=n)add(r+1,-val);
    			change(1,l,val);if(r+1<=n)change(1,r+1,-val);
    		}
    		else if(ch=='Q'){
    			ll l,r;l=read();r=read();
    			printf("%lld
    ",gcd(a[l]+ask(l),query(1,l+1,r)));
    		}
    	}
        return 0;
    }
    
    
  • 相关阅读:
    不用if/else swich for while实现累加
    1.java数据结构
    青蛙跳台阶问题
    next与nextLine
    9.遗传算法
    Docker镜像管理
    Docker镜像管理
    CentOS 6.7安装Docker
    CentOS 6.7安装Docker
    数字三角形_递归_递推(动态规划)
  • 原文地址:https://www.cnblogs.com/PPXppx/p/11655328.html
Copyright © 2011-2022 走看看