1. 程式人生 > >cf-914D-線段樹

cf-914D-線段樹

http://codeforces.com/contest/914/problem/D

 題目大意是給出一個數列,進行兩種操作,一個是將位置i的數置為x,另一個操作是詢問[l,r]內的數的gcd是不是x,我們可以至多更改這個區間內的一個數。

線段樹維護區間gcd,詢問的時候統計有多少個數不是x的倍數,當數量大於1的時候就可以直接return了,因為答案顯然已經是NO了,沒這一句的話會T。

  

 1 #include<bits/stdc++.h>
 2 using namespace std;
 3 #define LL long long  
 4 #define
ULL unsigned long long 5 const int maxn=500050; 6 int gcd(int a,int b){ 7 return b==0?a:gcd(b,a%b); 8 } 9 struct sg_tree{ 10 #define mid ((L+R)>>1) 11 #define lc (id<<1) 12 #define rc (id<<1|1) 13 14 int g[maxn<<2],N; 15 void build(int id,int
L,int R){ 16 if(L==R){ 17 scanf("%d",&g[id]); 18 return; 19 } 20 build(lc,L,mid); 21 build(rc,mid+1,R); 22 g[id]=gcd(g[lc],g[rc]); 23 } 24 25 void change(int id,int L,int R,int tar,int v){ 26 if(L==R){ 27
g[id]=v; 28 return; 29 } 30 if(tar<=mid) change(lc,L,mid,tar,v); 31 else change(rc,mid+1,R,tar,v); 32 g[id]=gcd(g[lc],g[rc]); 33 } 34 35 void ask(int id,int L,int R,int l,int r,int x,int &tot){ 36 if(tot>1) return; 37 if(L==R){ 38 if(g[id]%x!=0) tot++; 39 return; 40 } 41 if(l<=mid){ 42 if(g[lc]%x!=0){ 43 ask(lc,L,mid,l,r,x,tot); 44 } 45 } 46 if(r>mid){ 47 if(g[rc]%x!=0){ 48 ask(rc,mid+1,R,l,r,x,tot); 49 } 50 } 51 } 52 }ac; 53 int main(){ 54 scanf("%d",&ac.N); 55 ac.build(1,1,ac.N); 56 int op,m,l,r,x,i; 57 scanf("%d",&m); 58 while(m--){ 59 scanf("%d",&op); 60 if(op==1){ 61 int ok=0; 62 scanf("%d%d%d",&l,&r,&x); 63 ac.ask(1,1,ac.N,l,r,x,ok); 64 ok<=1?puts("YES"):puts("NO"); 65 } 66 else{ 67 scanf("%d%d",&i,&x); 68 ac.change(1,1,ac.N,i,x); 69 } 70 } 71 return 0; 72 }