1. 程式人生 > 實用技巧 >CodeForces - 914D Bash and a Tough Math Puzzle 數論,線段樹

CodeForces - 914D Bash and a Tough Math Puzzle 數論,線段樹

n <= 5e5

兩種操作:
1.詢問 L ,R 能否通過修改一個數使得區間gcd為x

2. 修改某點的大小

首先聯想到可以用線段樹維護區間性質,單點修改。

如果判斷1?

如果區間中所有數都是x的倍數,那麼只需修改任意一個數變為x就可以。

如果區間中大於一個數不是x的倍數,由於僅僅能修改一次,所以肯定是false

剩下的情況就都可以了

注意線段樹細節

struct Tree {
    int l, r, val , gcd;
};

Tree node[maxn * 4];
int a[maxn];


void Pushup(int i) {
    node[i].gcd = gcd(node[i << 1
].gcd, node[i << 1 | 1].gcd); } void Build(int i, int l, int r) { node[i].l = l; node[i].r = r; if (l == r) { node[i].gcd = a[l]; return; } int mid = l + r >> 1; Build(i << 1, l, mid); Build(i << 1 | 1, mid + 1, r); Pushup(i); }
void update(int i, int l, int r, int v) { if (node[i].l == node[i].r) { node[i].val = v; node[i].gcd = v; return; } int mid = node[i].l + node[i].r >> 1; if (r <= mid) update(i << 1, l, r, v); else if (l > mid) update(i << 1 | 1, l, r, v);
else { update(i << 1, l, mid, v); update(i << 1 | 1, mid + 1, r, v); } Pushup(i); } int query(int rt, int L,int R, int x) { int ans = 0; int mid = node[rt].l + node[rt].r >> 1; if (L <= node[rt].l && R >= node[rt].r && node[rt].gcd % x == 0) return 0; if (node[rt].l == node[rt].r) return 1; if (L <= mid) ans += query(rt << 1, L, R, x); if (ans >= 2) return ans; if (R > mid) ans += query(rt << 1 | 1, L, R, x); return ans; } int main() { int k; int L, R, X; int n = readint(); for (int i = 1; i <= n; i++) a[i] = readint(); Build(1, 1, n); int q = readint(); while (q--) { k = readint(); if (k == 1) { L = readint(), R = readint(); X = readint(); if (query(1, L, R, X) > 1) puts("NO"); else puts("YES"); } else { L = readint(), X = readint(); update(1, L, L, X); } } }