bzoj4373 算術天才⑨與等差數列 [線段樹+平衡樹]

Description:
單點修改,詢問區間是否構成公差爲k 的等差數列。


Solution:
公差爲k 的等差數列可以改成以下性質:
1 .相鄰兩項差的gcd
2 .最大值與最小值的差爲(rl)k
3 .區間內沒有相同的數
所以第一項維護差的gcd ,維護區間最大最小值,第三項給每個權值開個平衡樹,記錄每個權值上次出現的位置pre ,每次查詢pre 最小值,如果<l 則說明沒有相同的。


#include <bits/stdc++.h>
using namespace std;
const int maxn = 3e5 + 5;
struct node {
    int mx, mn, gcd, pre;
} t[maxn * 4];
int n, m, last, id;
int a[maxn];
set<int> s[maxn * 2];
map<int, int> mp;
int read() {
    int x = 0, f = 1;
    char c = getchar();
    while(!isdigit(c)) {
        if(c == '-') {
            f = -1;
        }
        c = getchar();
    }
    while(isdigit(c)) {
        x = x * 10 + c - '0';
        c = getchar();
    }
    return x * f;
}
void build(int l, int r, int x) {
    if(l == r) {
        t[x].mx = t[x].mn = a[l];
        t[x].gcd = abs(a[l] - a[l - 1]);
        return;
    }
    int mid = (l + r) >> 1;
    build(l, mid, x << 1);
    build(mid + 1, r, x << 1 | 1);
    t[x].mx = max(t[x << 1].mx, t[x << 1 | 1].mx);
    t[x].mn = min(t[x << 1].mn, t[x << 1 | 1].mn);
    t[x].gcd = __gcd(t[x << 1].gcd, t[x << 1 | 1].gcd);
}
void update_1(int l, int r, int x, int p, int d) {
    if(l == r) {
        t[x].mx = t[x].mn = d;
        return;
    }
    int mid = (l + r) >> 1;
    if(p <= mid) {
        update_1(l, mid, x << 1, p, d);
    } else {
        update_1(mid + 1, r, x << 1 | 1, p, d);
    }
    t[x].mx = max(t[x << 1].mx, t[x << 1 | 1].mx);
    t[x].mn = min(t[x << 1].mn, t[x << 1 | 1].mn);
}
void update_2(int l, int r, int x, int p, int d) {
    if(l == r) {
        t[x].gcd = abs(d);
        return;
    }
    int mid = (l + r) >> 1;
    if(p <= mid) {
        update_2(l, mid, x << 1, p, d);
    } else {
        update_2(mid + 1, r, x << 1 | 1, p, d);
    }
    t[x].gcd = __gcd(t[x << 1].gcd, t[x << 1 | 1].gcd);
} 
void update_3(int l, int r, int x, int p, int d) {
    if(l == r) {
        t[x].pre = d;
        return;
    }
    int mid = (l + r) >> 1;
    if(p <= mid) {
        update_3(l, mid, x << 1, p, d);
    } else {
        update_3(mid + 1, r, x << 1 | 1, p, d);
    }
    t[x].pre = max(t[x << 1].pre, t[x << 1 | 1].pre);
}
int query_mx(int l, int r, int x, int a, int b) {
    if(l > b || r < a) {
        return 0;
    }
    if(l >= a && r <= b) {
        return t[x].mx;
    }
    int mid = (l + r) >> 1;
    return max(query_mx(l, mid, x << 1, a, b), query_mx(mid + 1, r, x << 1 | 1, a, b));
}
int query_mn(int l, int r, int x, int a, int b) {
    if(l > b || r < a) {
        return 1e9 + 1;
    }
    if(l >= a && r <= b) {
        return t[x].mn;
    }
    int mid = (l + r) >> 1;
    return min(query_mn(l, mid, x << 1, a, b), query_mn(mid + 1, r, x << 1 | 1, a, b));
}
int query_gcd(int l, int r, int x, int a, int b) {
    if(l > b || r < a) {
        return 0;
    }
    if(l >= a && r <= b) {
        return t[x].gcd;
    }
    int mid = (l + r) >> 1;
    return __gcd(query_gcd(l, mid, x << 1, a, b), query_gcd(mid + 1, r, x << 1 | 1, a, b));
}
int query_pre(int l, int r, int x, int a, int b) {
    if(l > b || r < a) {
        return 0;
    }
    if(l >= a && r <= b) {
        return t[x].pre;
    }
    int mid = (l + r) >> 1;
    return max(query_pre(l, mid, x << 1, a, b), query_pre(mid + 1, r, x << 1 | 1, a, b));
}
int main() {
    n = read();
    m = read();
    for(int i = 1; i <= n; ++i) {
        a[i] = read();
        if(mp.find(a[i]) == mp.end()) {
            mp[a[i]] = ++id;
            s[id].insert(0);
        }
    }
    build(1, n, 1);
    for(int i = 1; i <= n; ++i) {
        update_3(1, n, 1, i, *(--s[mp[a[i]]].end()));
        s[mp[a[i]]].insert(i);
    }
    while(m--) {
        int opt = read(), l, r, p, x, y, k, mx, mn, t;
        if(opt == 1) {
            x = read() ^ last;
            y = read() ^ last;
            p = mp[a[x]];
            s[p].erase(x);
            set<int> :: iterator it = s[p].lower_bound(x);
            if(it != s[p].end()) {
                t = *it;
                update_3(1, n, 1, t, *(--it));
            }
            if(mp.find(y) == mp.end()) {
                mp[y] = ++id;
                s[id].insert(0);
            }
            p = mp[y];
            it = s[p].lower_bound(x);
            if(it != s[p].end()) {
                update_3(1, n, 1, *it, x);
            }
            update_3(1, n, 1, x, *(--it));
            s[p].insert(x);
            a[x] = y;
            update_1(1, n, 1, x, y);
            update_2(1, n, 1, x, y - a[x - 1]);
            if(x + 1 <= n) {
                update_2(1, n, 1, x + 1, a[x + 1] - y); 
            }           
        } else {
            l = read() ^ last;
            r = read() ^ last;
            k = read() ^ last;
            if(l > r) {
                swap(l, r);
            }
            mx = query_mx(1, n, 1, l, r);
            mn = query_mn(1, n, 1, l, r);
            if(l == r) {
                ++last;
                puts("Yes");
            } else if(k == 0) {
                if(mn == mx) {
                    ++last;
                    puts("Yes");
                } else {
                    puts("No"); 
                }
            } else if(mx - mn == (long long)(r - l) * k && query_gcd(1, n, 1, l + 1, r) % k == 0 && query_pre(1, n, 1, l, r) < l) {
                ++last;
                puts("Yes");
            } else {
                puts("No");         
            }
        }
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章