1. 程式人生 > >codeforces 914 D Bash and a Tough Math Puzzle

codeforces 914 D Bash and a Tough Math Puzzle

splay col cst hide spl hang sin algorithm d+

技術分享圖片
 1 #include<iostream>
 2 #include<cstring>
 3 #include<cstdio>
 4 #include<algorithm>
 5 #include<cstdio>
 6 using namespace std;
 7 const int N=500100;
 8 int n,a[N],m;
 9 struct tree{
10     int l,r,gcd;
11 }tr[N*5];
12 int gcd(int x,int y){
13     if(y==0)return x;
14     else
return gcd(y,x%y); 15 } 16 void build(int l,int r,int now){ 17 tr[now].l=l;tr[now].r=r; 18 if(l==r){ 19 tr[now].gcd=a[l]; 20 return; 21 } 22 int mid=(l+r)>>1; 23 build(l,mid,now*2); 24 build(mid+1,r,now*2+1); 25 tr[now].gcd=gcd(tr[now*2].gcd,tr[now*2
+1].gcd); 26 } 27 void change(int x,int y,int now){ 28 // cout<<tr[now].l<<" "<<tr[now].r<<" "<<x<<endl; 29 if(tr[now].l==x&&tr[now].r==x){ 30 tr[now].gcd=y; 31 return ; 32 } 33 int mid=(tr[now].l+tr[now].r)>>1; 34 if(x>mid)change(x,y,now*2
+1); 35 else change(x,y,now*2); 36 tr[now].gcd=gcd(tr[now*2].gcd,tr[now*2+1].gcd); 37 } 38 int check(int l,int r,int x,int now){ 39 if(tr[now].gcd%x==0)return 0; 40 if(tr[now].l==l&&tr[now].r==r){ 41 if(l==r)return 1; 42 if(tr[now*2].gcd%x==0)return check(tr[now*2+1].l,tr[now*2+1].r,x,now*2+1); 43 if(tr[now*2+1].gcd%x==0)return check(tr[now*2].l,tr[now*2].r,x,now*2); 44 return 2; 45 } 46 int mid=(tr[now].l+tr[now].r)>>1; 47 if(l>mid)return check(l,r,x,now*2+1); 48 else if(r<=mid)return check(l,r,x,now*2); 49 else{ 50 return check(l,mid,x,now*2)+check(mid+1,r,x,now*2+1); 51 } 52 } 53 int main(){ 54 scanf("%d",&n); 55 for(int i=1;i<=n;i++){ 56 scanf("%d",&a[i]); 57 } 58 build(1,n,1); 59 scanf("%d",&m); 60 for(int i=1;i<=m;i++){ 61 int k; 62 scanf("%d",&k); 63 if(k==1){ 64 int l,r,x; 65 scanf("%d%d%d",&l,&r,&x); 66 if(check(l,r,x,1)<=1)printf("YES\n"); 67 else printf("NO\n"); 68 } 69 else{ 70 int x,y; 71 scanf("%d%d",&x,&y); 72 change(x,y,1); 73 } 74 } 75 return 0; 76 }
View Code

題意

?給出一段序列(1≤n≤5*105),兩個操作(1≤q≤4*105)

?操作1 給出l,r,x

?求區間l-r的gcd,如果至多能改掉區間內的一個數,使gcd是x的倍數,那麽輸出YES,否則輸出NO

?操作2 給出pos,x

?將序列中pos位置上的數字改為x

題解

線段樹,維護區間的gcd

因為題目詢問刪除一個數,我們把整個區間分成兩塊,如果兩邊的gcd都是x的倍數顯然是可以的,如果都不是gcd的倍數,就不行了,因為使兩個gcd的gcd為x的倍數,這兩個gcd應該都至少含有x因子。如果一個gcd是x的倍數,一個不是,那就遞歸處理不是的那個區間。

codeforces 914 D Bash and a Tough Math Puzzle