[BZOJ4085][Sdoi2015]quality && 线段树 (TLE)

线段树维护F[ai-1], F[ai-1 + 1], F[ai-1 - 1], F[ai+1], F[ai+1 + 1], F[ai+1 - 1]

以及两两乘积和

加一的时候可以直接用递推式用保存的F值求出新的值

减一的时候也可以解方程求值

然后 写码农题

然而此题常数太卡 在jzoj上都600ms了 BZ上还是过不去 弃疗了

#include
#include
#include
#include
#include
#define SF scanf
#define PF printf
using namespace std;
typedef int LL;
inline int read() {
    int x=0,f=1; char ch=getchar();
    while(ch<'0'||ch>'9') {if(ch=='-') f=-1; ch=getchar(); }
    while(ch>='0'&&ch<='9') {x=x*10+ch-'0'; ch=getchar(); }
    return x*f;
}
const int MOD = 1000000007;
const int MAXN = 300000;
int a, b, n, m, inv, L, R, Y, Z;
int p[MAXN+10][4];
int pow_mod(int x, int k) {
    int ret = 1;
    while(k) {
        if(k & 1) ret = 1LL * ret * x % MOD;
        x = 1LL * x * x % MOD;
        k >>= 1;
    }
    return ret;
}
struct Matrix {
    int a[3][3], r, c;
    void set(int n) {
        memset(a, 0, sizeof(a));
        r = c = n;
        for(int i = 0; i < n; i++) a[i][i] = 1;
    }
    Matrix operator * (const Matrix &t) const {
        Matrix ret; memset(ret.a, 0, sizeof(ret.a));
        ret.r = r; ret.c = t.c;
        for(int i = 0; i < r; i++)
            for(int k = 0; k < c; k++)
                for(int j = 0; j < 2; j++)
                    ret.a[i][j] = (ret.a[i][j] + 1LL * a[i][k] * t.a[k][j] % MOD) % MOD;
        ret.a[2][2] = 1;
        return ret;
    }
} A, B, power[40], unit;
Matrix pow_mod(int k) {
    Matrix ret = unit;
    int i = 1;
    while(k) {
        if(k & 1) ret = ret * power[i];
        k >>= 1;
        i++;
    }
    return ret;
}
void getmat(int i) {
    Matrix t = A * pow_mod(p[i][0]-2);
    p[i][1] = t.a[0][1]; p[i][2] = t.a[0][0];
}
void build() {
    A.r = 1; A.c = 3;
    A.a[0][0] = 2; A.a[0][1] = 1; A.a[0][2] = 1;
     
    B.r = B.c = 3;
    B.a[0][0] = 1; B.a[1][0] = a; B.a[2][0] = b;
    B.a[0][1] = 1; B.a[2][2] = 1;
    for(int i = 1; i <= 32; i++) {
        power[i] = B;
        B = B * B;
    }
}
    #define ls (x<<1)
    #define rs (x<<1|1)
    struct Node {
        int s[2][3], ch[3][3], l, r, lz[2];
    } t[MAXN*4+10];
    inline void up(int x) {
        for(int i = 0; i < 3; i++)
            for(int j = 0; j < 3; j++)
                t[x].ch[i][j] = (t[ls].ch[i][j] + t[rs].ch[i][j]) % MOD;
        for(int i = 0; i < 2; i++)
            for(int j = 0; j < 3; j++)
                t[x].s[i][j] = (t[ls].s[i][j] + t[rs].s[i][j]) % MOD;
    }
    inline void add(int x, int l) {
        for(int i = 0; i < 2; i++) t[x].s[l][i] = t[x].s[l][i+1];
        t[x].s[l][2] = (t[x].s[l][1] + 1LL * t[x].s[l][0] * a + 1LL * b * (t[x].r - t[x].l + 1)) % MOD;
        if(l == 0) {
            for(int i = 0; i < 2; i++)
                for(int j = 0; j < 3; j++)
                    t[x].ch[i][j] = t[x].ch[i+1][j];
            for(int j = 0; j < 3; j++) t[x].ch[2][j] = (t[x].ch[1][j] + 1LL * t[x].ch[0][j] * a+ 1LL * b * t[x].s[1][j]) % MOD;
        }
        if(l == 1) {
            for(int i = 0; i < 3; i++)
                for(int j = 0; j < 2; j++)
                    t[x].ch[i][j] = t[x].ch[i][j+1];
            for(int i = 0; i < 3; i++) t[x].ch[i][2] = (t[x].ch[i][1] + 1LL * t[x].ch[i][0] * a + 1LL * b * t[x].s[0][i]) % MOD;
        }
    }
    inline void dec(int x, int l) {
        if(a == 0) {
            for(int i = 1; i+1; i--) t[x].s[l][i+1] = t[x].s[l][i];
            t[x].s[l][0] = (t[x].s[l][1] - 1LL * b * (t[x].r-t[x].l+1) % MOD + MOD) % MOD;
            if(l == 0) {
                for(int i = 1; i+1; i--)
                    for(int j = 0; j < 3; j++)
                        t[x].ch[i+1][j] = t[x].ch[i][j];
                for(int i = 0; i < 3; i++) t[x].ch[0][i] = (t[x].ch[1][i] - 1LL * b * t[x].s[1][i] % MOD + MOD) % MOD;
            }
            else {
                for(int i = 1; i+1; i--)
                    for(int j = 0; j < 3; j++)
                        t[x].ch[j][i+1] = t[x].ch[j][i];
                for(int i = 0; i < 3; i++) t[x].ch[i][0] = (t[x].ch[i][1] - 1LL * b * t[x].s[0][i] % MOD + MOD) % MOD;
            }
            return ;
        }
        for(int i = 1; i+1; i--) t[x].s[l][i+1] = t[x].s[l][i];
        t[x].s[l][0] = ((t[x].s[l][2] - t[x].s[l][1] - 1LL * b * (t[x].r-t[x].l+1) % MOD) * inv % MOD + MOD) % MOD;
        if(l == 0) {
            for(int i = 1; i+1; i--)
                for(int j = 0; j < 3; j++)
                    t[x].ch[i+1][j] = t[x].ch[i][j];
            for(int i = 0; i < 3; i++) t[x].ch[0][i] = ((t[x].ch[2][i] - t[x].ch[1][i] - 1LL * b * t[x].s[1][i] % MOD) % MOD * inv % MOD + MOD) % MOD;
        }
        if(l == 1) {
            for(int i = 1; i+1; i--) 
                for(int j = 0; j < 3; j++)
                    t[x].ch[j][i+1] = t[x].ch[j][i];
            for(int i = 0; i < 3; i++) t[x].ch[i][0] = ((t[x].ch[i][2] - t[x].ch[i][1] - 1LL * b * t[x].s[0][i] % MOD) % MOD * inv % MOD + MOD) % MOD;
        }
    }
    inline void pushdown(int x, int y, int z) {
        if(z > 0) for(int i = 1; i <= z; i++) add(x, y);
        else if(z < 0)
            for(int i = -1; i >= z; i--) dec(x, y);
    }
    inline void pb(int x) {
        for(int l = 0; l < 2; l++) {
            pushdown(ls, l, t[x].lz[l]);
            pushdown(rs, l, t[x].lz[l]);
            t[ls].lz[l] += t[x].lz[l];
            t[rs].lz[l] += t[x].lz[l];
            t[x].lz[l] = 0;
        }
    }
    inline void build(int x, int l, int r) {
        Node &u = t[x];
        u.l = l; u.r = r;
        if(l == r) {
            for(int i = 0; i < 3; i++) {
                u.s[0][i] = p[l-1][i+1];
                u.s[1][i] = p[l+1][i+1];
            }
            for(int i = 0; i < 3; i++)
                for(int j = 0; j < 3; j++)
                    u.ch[i][j] = 1LL * u.s[0][i] * u.s[1][j] % MOD;
            return ;
        }
        int mid = l+r >> 1;
        build(ls, l, mid);
        build(rs, mid+1, r);
        up(x);
    }
    inline void add(int x) {
        int l = t[x].l, r = t[x].r;
        if(l > R || r < L) return ;
        if(L <= l && r <= R) {
            t[x].lz[Y] += Z;
            pushdown(x, Y, Z);
            return ;
        }
        pb(x);
        add(ls);
        add(rs);
        up(x);
    }
    inline int que(int x) {
        int l = t[x].l, r = t[x].r;
        if(l > R || r < L) return 0;
        if(L <= l && r <= R) return t[x].ch[2][0];
        pb(x);
        return (que(ls) + que(rs)) % MOD;
    }
int main() {
    SF("%d%d%d%d", &n, &m, &a, &b);
    inv = pow_mod(a, MOD-2);
    unit.set(3);
    build();
    for(int i = 1; i <= n; i++)  {
        SF("%d", &p[i][0]);
        getmat(i);
        p[i][3] = (p[i][2] + 1LL * a * p[i][1] % MOD + b) % MOD;
    }
    build(1, 2, n-1);
    char op[10];
    while(m--) {
        SF("%s", op);
        int l, r;SF("%d%d", &l, &r);
        if(op[0] == 'p') {
            L = l+1; R = r+1;
            Y = 0; Z = 1;
            add(1);
            L = l-1; R = r-1;
            Y = 1; Z = 1;
            add(1);
        }
        else if(op[0] == 'm') {
            L = l+1; R = r+1;
            Y = 0; Z = -1;
            add(1);
            L = l-1; R = r-1;
            Y = 1; Z = -1;
            add(1);
        }
        else {
            L = l+1; R = r-1;
            PF("%d\n", que(1));
        }
    }
}


你可能感兴趣的:(BZOJ,线段树)