小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;
}