2821: 小Y学长的GCD难题——Power OJ(线段树,区间最大公约数)

小Y:给你一个序列a,你会计算a[l]到a[r]的GCD吗?

小Z:这不是sb题吗?

小Y:如果给你q次询问呢?

小Z:还是很简单啊!!!

小Y:如果我可以修改某个区间的值为同一个值呢?

小Z:这尼玛能做???

你能帮助小Z计算出区间l到r的GCD吗?
Input
第一行输入一个TT(1≤T≤5),接下来有T组测试。 对于每一组测试: 第一行输入n,q(∑n≤2×105,∑q≤2×105),表示序列aa的长度和询问次数 第二行n个整数ai(1≤ai≤231 −1≤ai≤231−1),表示序列a的初始值。 接下来q行,每行代表一个操作:
操作1:1 l r x (1≤l,r≤n,1≤231−1)表示将区间[l,r]内的所有数全部修改为xx
操作2:2 l r (1≤l,r≤n)表示询问区间[l,r]的GCD
Output
每行输出一个整数表示答案
Sample Input
Raw

1
4 3
2 3 6 9
2 1 4
1 1 1 3
2 1 4
Sample Output
Raw

1
3


解题思路:这是一个线段树的模板题,lazy标记的时候注意一下细节。

#include <cstdio>
#include<algorithm>
using namespace std;
typedef long long ll;
const int maxn = 1e6+100;
int gcd(int a,int b)//辗转相除法
{
	if(b==0) return a;
	else return gcd(b,a%b);
}
struct node
{
    ll sum,lazy;
}tree[maxn<<2];
int n, num[maxn];
void pushup(long long root)//向上维护最大公约数
{
    tree[root].sum = gcd(tree[root<<1].sum , tree[root<<1|1].sum);
}
void pushdown(ll root,ll l,ll r)//向下传递参数
{
    if(tree[root].lazy == 0)
        return ;
    int chl = root<<1;
    int chr = root<<1|1;
    int mid = l + r>>1;
    tree[chl].sum = tree[root].lazy;
    tree[chr].sum = tree[root].lazy;
    tree[chl].lazy = tree[root].lazy;
    tree[chr].lazy = tree[root].lazy;
    tree[root].lazy = 0;
}

void buildtree(ll l,ll r,ll root)//建树
{
    tree[root].lazy = 0;
    if(l == r)
    {
        tree[root].sum=num[l];
        return ;
    }
    ll mid = (l + r) >> 1;
    buildtree(l,mid,root<<1);
    buildtree(mid+1,r,root<<1|1);
    pushup(root);
}

ll query(ll ql,ll qr,ll l,ll r,ll root)//查询
{
    if(l == ql && qr ==r)
    {
        return tree[root].sum;
    }
    ll mid = (l + r)>>1;
    pushdown(root,l,r);
    if(qr <= mid)
    {
        return query(ql,qr,l,mid,root<<1);
    }
    else if(ql > mid)
    {
        return query(ql,qr,mid+1,r,root<<1|1);
    }
    else
        return gcd(query(mid+1,qr,mid+1,r,root<<1|1), query(ql,mid,l,mid,root<<1));
}

void change(ll ql,ll qr,ll l,ll r,ll root,ll h)//修改
{
    if(l == ql && qr==r)
    {
        tree[root].lazy = h;
        tree[root].sum = h;
        return;
    }
    pushdown(root,l,r);
    ll mid = (l + r) >> 1;
    if(qr <= mid)
        change(ql,qr,l,mid,root<<1,h);
    else if(ql > mid)
        change(ql,qr,mid+1,r,root<<1|1,h);
    else
    {
        change(ql,mid,l,mid,root<<1,h);
        change(mid+1,qr,mid+1,r,root<<1|1,h);
    }
    pushup(root);
}

int main()
{
    int t,n,q;
    int a,b,c,d;
    scanf("%d",&t);
    while(t--){
        scanf("%d%d",&n,&q);
        for(int i=1;i<=n;i++){
            scanf("%d",&num[i]);
        }
        buildtree(1,n,1);
        while(q--){
            scanf("%d",&a);
            if(a==1){
                scanf("%d%d%d",&b,&c,&d);
                change(b,c,1,n,1,d);
            }
            if(a==2){
                scanf("%d%d",&b,&c);
                printf("%d\n",query(b,c,1,n,1));
            }
        }
    }

    return 0;
}

发布了36 篇原创文章 · 获赞 10 · 访问量 1923

猜你喜欢

转载自blog.csdn.net/weixin_44003265/article/details/97417261