題目大意:
給你一個序列,你要在這個序列上進行次操作,操作表示判斷是否序列區間中所有數的,如果不等於你可以修改其中一個數的值。操作。
思路:
注意到也就是說你的所有操作要在內完成才能通過這題,所以我們考慮採用線段樹來解決這題。操作二比較簡單就是基礎的單點修改,我們來考慮一下操作一,當 mod 也就是說這個區間內所有的數都是的倍數,那麼我們隨便修改其中一個數爲,就會有整體的.當一個區間 mod ,也就是說這個區間至少有一個數不是的倍數。但是我們無法確定是哪個數,所有我們需要遞歸要葉子節點才能確定,如果到達葉子節點並且這個節點 mod ,說明要想使得那麼這個數必須要修改,我們用來統計需要修改的節點個數。如果當前區間左右兒子都不是的倍數必要要修改兩個數,我們直接剪枝令。最後根據來輸出就行了。
總結:線段樹維護區間。利用性質剪枝以及思考,總體不是很難。還有需要注意的就是當一個區間 mod ,需要一直遞歸到葉子節點才能判斷,不能直接,因爲可能在某一個子區間有左右兒子 mod 都不等於0。
代碼:
#include<bits/stdc++.h>
using namespace std;
const int maxn = 5e5 + 10;
typedef long long int ll;
struct seg{
int l,r;
int gcd;
seg(){}
seg(int a,int b):l(a),r(b){}
}tree[maxn << 2];
void build(int id,int l,int r){
tree[id] = {l,r};
if(l == r){
scanf("%d",&tree[id].gcd);
return ;
}
int mid = l + r >> 1;
build(id << 1,l,mid);
build((id << 1) + 1,mid + 1, r);
tree[id].gcd = __gcd(tree[id << 1].gcd,tree[(id << 1) + 1].gcd);
}
void update(int id,int a,int b){
if(tree[id].l == tree[id].r && tree[id].l == a){
tree[id].gcd = b;
return ;
}
int mid = tree[id].l + tree[id].r >> 1;
if(a <= mid)update(id << 1,a,b);
else update((id << 1) + 1,a,b);
tree[id].gcd = __gcd(tree[id << 1].gcd,tree[(id << 1) + 1].gcd);
}
void query(int id,int l,int r,int x,int &cnt){
if(cnt >= 2){return;}
if(tree[id].l >= l && tree[id].r <= r){
if(tree[id].gcd % x == 0)return ;
else if(tree[id].l == tree[id].r){cnt++;return;}
if(tree[id << 1].gcd % x != 0 && tree[(id << 1) + 1].gcd % x != 0){
cnt = 2;return;
}
if(tree[id << 1].gcd % x != 0)
query(id << 1,l,r,x,cnt);
if(tree[(id << 1) + 1].gcd % x != 0)
query((id << 1) + 1,l,r,x,cnt);
return;
}
int mid = tree[id].l + tree[id].r >> 1;
if(r <= mid) query(id << 1,l,r,x,cnt);
else if(l > mid) query((id << 1) + 1,l,r,x,cnt);
else query(id << 1,l,r,x,cnt) , query((id << 1) + 1,l,r,x,cnt);
}
void solved(){
int n;scanf("%d",&n);
build(1,1,n);
int q;scanf("%d",&q);
int l,r,x;
while(q--){
int ins;scanf("%d",&ins);
if(ins == 1){
int cnt = 0;
scanf("%d%d%d",&l,&r,&x);
if(l == r){cout<<"YES"<<endl;continue;}
query(1,l,r,x,cnt);
if(cnt <= 1)printf("YES\n");
else printf("NO\n");
}
if(ins == 2){
ll i,y;
scanf("%lld%lld",&i,&y);
update(1,i,y);
}
}
}
int main(){
solved();
return 0;
}