--- title: Codeforce 914 D. Bash and a Tough Math Puzzle 解析(線段樹、數論) description: "Codeforce 914 D. Bash and a Tough Math Puzzle 解析(線段樹、數論)" --- <meta name="robots" content="Codeforce 914 D. Bash and a Tough Math Puzzle 解析(線段樹、數論)"> <!-- toc --> # Codeforce 914 D. Bash and a Tough Math Puzzle 解析(線段樹、數論) 今天我們來看看CF914D [題目連結](https://codeforces.com/problemset/problem/914/D) > **題目** 給你一個長度為$n$的數列$a$,每次玩家會選擇一個區間猜$g.c.d.$的值,或者改變數列中的某個數字。而猜中不一定要完全準確,如果玩家能夠改動一個區間中的數字讓$g.c.d.$完全猜中也是可以的。 ### 前言 我對線段樹還是不熟阿,一開始一直感覺$g.c.d.$沒辦法用線段樹維護... ### 想法 上模板,從維護區間和的模板改成維護$g.c.d.$(這就是為什麼我code中的元素修改函式叫做$add$)。 接著注意到一件事,猜中的條件是:假設區間中有$k$個數字,只要其中$k-1$個數字可以被$val$($val\stackrel{def}{=}$玩家猜的數字)整除就可以了(如果這$k-1$個數字的$g.c.d.\ge val$,那麼只要把最後那個數字改成$val$就好)。 一開始我就直接這樣實作,每次從$root$開始往下找有幾個數字可以被整除,整個區間都看過以後再來檢查是否$\ge k-1$,但是發現這樣會TLE。 查網路後發現我們必須用一個全域變數去計算:有多少在區間中數字不可被整除,如果發現數量$>1$就要馬上跳離搜尋,如此一來就不會TLE了。 ($almost$函式是這題的重點,寫法和模板有點差異,要小心實作。) ### 程式碼: ```cpp= const int _n=5e5+10; int n,a[_n],q,tt,tot=0; namespace Seg{ int nn; int t[_n<<2]; void pull(int v){t[v]=__gcd(t[2*v+1],t[2*v+2]);} void apply(int v, int val){t[v]=val;} void build(int v, int l, int r){ if(l+1==r)t[v]=a[l]; else{int m=(l+r)>>1;build(2*v+1,l,m),build(2*v+2,m,r);pull(v);} } void add(int v,int l,int r,int ql,int qr,int val){ if(r<=ql or qr<=l)return; else if(ql<=l and r<=qr)apply(v,val); else{ int m=(l+r)>>1; add(2*v+1,l,m,ql,qr,val),add(2*v+2,m,r,ql,qr,val); pull(v); } } void add(int pos,ll val){add(0,0,nn,pos,pos+1,val);} void init(int n_){nn=n_;build(0,0,nn);} void almost(int v,int l,int r,int ql,int qr,int val){ if(tot>1)return; if(r<=ql or qr<=l)return; else if(ql<=l and r<=qr and t[v]%val==0)return; else{ if(l+1==r){tot++;return;} int m=(l+r)>>1; almost(2*v+1,l,m,ql,qr,val),almost(2*v+2,m,r,ql,qr,val); } } } main(void) {cin.tie(0);ios_base::sync_with_stdio(0); cin>>n;rep(i,0,n)cin>>a[i]; cin>>q; Seg::init(n); while(q--){ cin>>tt; if(tt==1){ int l,r,x;cin>>l>>r>>x;l--,r--; tot=0;Seg::almost(0,0,n,l,r+1,x); if(tot<=1)cout<<"YES\n"; else cout<<"NO\n"; }else{ int i,y;cin>>i>>y;i--; Seg::add(i,y); } } return 0; } ``` 標頭、模板請點Submission看 [Submission](https://codeforces.com/contest/914/submission/90432062)