BZOJ 4373 算术天才⑨与等差数列

来源:互联网 发布:java输出九九乘法表 编辑:程序博客网 时间:2024/05/14 03:28

题解

考虑一个数列Ai(排序后)为等差数列且公差为K的充要条件是:
n=0
或者K=0max=min
或者maxmin=n×Kgcd(di|2in)=K
其中di=AiAi1
故题目变为一道线段树题。

写法比较丑陋,把线段树套了一个template,造成了模板100+,代码50+的悲剧。。

code

#include <algorithm>#include <bitset>#include <cassert>#include <cmath>#include <cstdio>#include <cstdlib>#include <cstring>#include <ctime>#include <deque>#include <iostream>#include <map>#include <queue>#include <set>#include <string>#include <vector>using namespace std;const int INF = 0x3f3f3f3f;template <class cInfo, class mInfo> struct Seg {    static int ql, qr;    static cInfo cv;    static mInfo mv;    static int *A;    static Seg* segR;    int l, r, m;    cInfo c;    Seg *ch[2];    Seg() { }    Seg(int l, int r) : l(l), r(r) {        m = (l + r) >> 1;        c = cInfo();        if (l == r) {            c = cInfo(A[l]);            ch[0] = ch[1] = 0;            return;        }        ch[0] = new(segR ++) Seg(l, m);        ch[1] = new(segR ++) Seg(m+1, r);        c = merge(ch[0]->c, ch[1]->c);    }//  void* operator new(unsigned, void* p) { return p; }    void update() {        if (ql <= l && r <= qr) {            merge(c, mv);            return;        }        if (ql <= m) ch[0]->update();        if (m < qr) ch[1]->update();        c = merge(ch[0]->c, ch[1]->c);    }    void query() {        if (ql <= l && r <= qr) {            cv = merge(cv, c);            return;        }        if (ql <= m) ch[0]->query();        if (m < qr) ch[1]->query();    }    void update(int _ql, const mInfo& _mv) {        ql = _ql; qr = _ql; mv = _mv; update();    }    cInfo query(int _ql, int _qr) {        ql = _ql; qr = _qr; new(&cv)cInfo(); query(); return cv;    }};const int MAXN = 1200010;const int maxn = 300010;struct cInfo {    int mx, mn;    cInfo() { mx = 0; mn = INF; }    cInfo(int v) { mx = mn = v; }};struct mInfo {    int v;    mInfo() { }    mInfo(int v) : v(v) { }};cInfo merge(const cInfo& A, const cInfo& B) {    cInfo C;    C.mx = max(A.mx, B.mx);    C.mn = min(A.mn, B.mn);    return C;}void merge(cInfo& A, const mInfo& B) {    if (B.v) new(&A)cInfo(B.v);}typedef Seg<cInfo, mInfo> Seg1;template<> int Seg1::ql=0;template<> int Seg1::qr=0;template<> cInfo Seg1::cv=cInfo();template<> mInfo Seg1::mv=mInfo();template<> int* Seg1::A = new int[maxn];template<> Seg1* Seg1::segR=0;struct cInfo2 {    int d;    cInfo2() { d = 0; }    cInfo2(int v) { d = v; }};struct mInfo2 {    int v;    mInfo2() { }    mInfo2(int v) : v(v) { }};cInfo2 merge(const cInfo2& A, const cInfo2& B) {    cInfo2 C;    C.d = __gcd(A.d, B.d);    return C;}void merge(cInfo2& A, const mInfo2& B) {    if (B.v) new(&A)cInfo(B.v);}typedef Seg<cInfo2, mInfo2> Seg2;template<> int Seg2::ql=0;template<> int Seg2::qr=0;template<> cInfo2 Seg2::cv=cInfo2();template<> mInfo2 Seg2::mv=mInfo2();template<> int* Seg2::A = new int[maxn];template<> Seg2* Seg2::segR=0;Seg1 segA[MAXN], *TA;Seg2 segd[MAXN], *Td;int n, m, z;bool solveq(int l, int r, int k) {    if (l == r) return 1;    cInfo c = TA->query(l, r);    if (k == 0 && c.mx == c.mn) return 1;    cInfo2 c2 = Td->query(l+1, r);    if (c.mn + (r-l) * k == c.mx && abs(c2.d) == k) return 1;    return 0;}int A[maxn];void solve() {    scanf("%d%d", &n, &m);    for (int i = 1; i <= n; ++ i) {        scanf("%d", A+i);        TA->A[i] = A[i]; Td->A[i] = A[i] - A[i-1];    }    TA->segR = segA; TA = new(TA->segR ++)Seg1(1, n);    Td->segR = segd; Td = new(Td->segR ++)Seg2(1, n);    z = 0;    for (int i = 1; i <= m; ++ i) {        int opt; scanf("%d", &opt);        if (opt == 1) {            int x, y; scanf("%d%d", &x, &y); x ^= z, y ^= z;            TA->update(x, y);            A[x] = y;            Td->update(x, A[x]-A[x-1]);            if (x+1 <= n) Td->update(x+1, A[x+1]-A[x]);        } else if (opt == 2) {            int l, r, k; scanf("%d%d%d", &l, &r, &k); l ^= z, r ^= z, k ^= z;            if (solveq(l, r, k)) { puts("Yes"); ++ z; } else puts("No");        }    }}int main() {//  freopen("4373.in", "r", stdin);    solve();//  for(;;);    return 0;}
0 0