Bash and a Tough Math Puzzle CodeForces - 914D (線段樹)
阿新 • • 發佈:2019-02-19
序列 單點 () void mes 意思 span esp sin
大意:給定序列, 單點修改, 區間詢問$[l,r]$內修改至多一個數後$gcd$能否為$x$
這題比較有意思了, 要註意到詢問等價於$[l,r]$內最多有1個數不為$x$的倍數
可以用線段樹維護gcd, 詢問操作每次二分找第一個不為$x$的倍數的數, 若找到兩個直接返回, 是$O(logn)$的
單點更新要大量計算gcd, 是$O(log^2n)$的
#include <iostream> #include <algorithm> #include <cstdio> #define REP(i,a,n) for(int i=a;i<=n;++i) #define mid ((l+r)>>1) #define lc (o<<1) #define rc (lc|1) #define ls lc,l,mid #define rs rc,mid+1,r using namespace std; typedef long long ll; ll gcd(ll a,ll b) {return b?gcd(b,a%b):a;} const int N = 5e5+10, INF = 0x3f3f3f3f; int n, m; int g[N<<2]; void build(int o, int l, int r) { if (l==r) return scanf("%d", g+o), void(); build(ls),build(rs); g[o]=gcd(g[lc],g[rc]); } void upd(int o, int l, int r, int x, int v) { if (l==r) return g[o]=v,void(); if (mid>=x) upd(ls,x,v); else upd(rs,x,v); g[o]=gcd(g[lc],g[rc]); } int query(int o, int l, int r, int ql, int qr, int v) { if (!(g[o]%v)) return 0; if (l==r) return 1; int ans = 0; if (mid>=ql) { ans += query(ls,ql,qr,v); if (ans>1) return ans; } if (mid<qr) ans += query(rs,ql,qr,v); return ans; } int main() { scanf("%d", &n); build(1,1,n); scanf("%d", &m); REP(i,1,m) { int op, l, r, x, v; scanf("%d", &op); if (op==1) { scanf("%d%d%d", &l, &r, &v); puts(query(1,1,n,l,r,v)<=1?"YES":"NO"); } else { scanf("%d%d", &x, &v); upd(1,1,n,x,v); } } }
Bash and a Tough Math Puzzle CodeForces - 914D (線段樹)