1. 程式人生 > >power oj 2821: 小Y學長的GCD難題(線段樹區間求最大公因數+區間修改)

power oj 2821: 小Y學長的GCD難題(線段樹區間求最大公因數+區間修改)

Description 

小Y:給你一個序列a,你會計算a[l]到a[r]的GCD嗎?

小Z:這不是sb題嗎?

小Y:如果給你q次詢問呢?

小Z:還是很簡單啊!!!

小Y:如果我可以修改某個區間的值為同一個值呢?

小Z:這尼瑪能做???

........

你能幫助小Z計算出區間l到r的GCD嗎?

Input 

第一行輸入一個TT(1≤T≤51≤T≤5),接下來有T組測試。 對於每一組測試: 第一行輸入nn,qq(∑n≤2×105∑n≤2×105,∑q≤2×105∑q≤2×105),表示序列aa的長度和詢問次數 第二行nn個整數aiai(1≤ai≤231−11≤ai≤231−1),表示序列aa的初始值。 接下來qq行,每行代表一個操作: 操作1:1 l r x (1≤l,r≤n,1≤231−11≤l,r≤n,1≤231−1)表示將區間[l,r][l,r]內的所有數全部修改為xx 操作2:2 l r   (1≤l,r≤n1≤l,r≤n)表示詢問區間[l,r][l,r]的GCD

Output 

每行輸出一個整數表示答案

1 4 3 2 3 6 9 2 1 4 1 1 1 3 2 1 4

1 3

PS:線段樹的裸題,注意細節。

AC程式碼:

#include <iostream>
#include<cstring>
#include<cstdio>
#include<algorithm>
#include<map>
#include<queue>
#include<set>
#include<cmath>
#include<stack>
#include<string>
const int maxn=2e5+10;
const int mod=1e9+7;
const int inf=1e8;
#define me(a,b) memset(a,b,sizeof(a))
typedef long long ll;
using namespace std;
int d[maxn<<2],lazy[maxn<<2];
int gcd(int a,int b)
{
    if(!b)
        return a;
    return gcd(b,a%b);
}
void update(int rt)
{
    d[rt]=gcd(d[rt<<1],d[rt<<1|1]);
}
void build(int l,int r,int rt)
{
    if(l==r)
    {
        scanf("%d",&d[rt]);
        return ;
    }
    int m=(l+r)>>1;
    build(l,m,rt<<1);
    build(m+1,r,rt<<1|1);
    update(rt);
}
void pushdown(int rt)
{
    if(lazy[rt])
    {
        d[rt<<1]=d[rt<<1|1]=lazy[rt];
        lazy[rt<<1]=lazy[rt<<1|1]=lazy[rt];
        lazy[rt]=0;
    }
}
void pushdate(int L,int R,int c,int l,int r,int rt)
{
    if(L<=l&&R>=r)
    {
        d[rt]=lazy[rt]=c;
        return ;
    }
    pushdown(rt);
    int m=(l+r)>>1;
    if(L<=m)
        pushdate(L,R,c,l,m,rt<<1);
    if(R>m)
        pushdate(L,R,c,m+1,r,rt<<1|1);
    update(rt);
}
int getgcd(int L,int R,int l,int r,int rt)
{
    if(L<=l&&R>=r)
        return d[rt];
    pushdown(rt);
    int m=(l+r)>>1;
    int a=0,b=0;
    if(L<=m)
        a=getgcd(L,R,l,m,rt<<1);
    if(R>m)
        b=getgcd(L,R,m+1,r,rt<<1|1);
    return gcd(a,b);
}
int main()
{
   int t;cin>>t;
   while(t--)
   {
       int n,q;
       cin>>n>>q;
       me(d,0),me(lazy,0);
       build(1,n,1);
       while(q--)
       {
           int x,a,b,c;
           scanf("%d",&x);
           if(x==1)
           {
               scanf("%d%d%d",&a,&b,&c);
               pushdate(min(a,b),max(a,b),c,1,n,1);
           }
           else
           {
               scanf("%d%d",&a,&b);
               printf("%d\n",getgcd(min(a,b),max(a,b),1,n,1));
           }
       }
   }
    return 0;
}