首页 > 其他 > 详细

bzoj 2962 序列操作(线段树)

时间:2015-02-20 22:02:20      阅读:503      评论:0      收藏:0      [点我收藏+]

题外话


做这道题我整个人都非常的绝望,推了一会发现是线段树裸题,然后调了N久一直是WA

情况是这样的技术分享

开始WA的几百毫秒的都是由于我比较SB造成的,可是跑了10几秒的程序我查了N久也查不出错

5000060000T_T

Description


n3

1:c

2:

3:cmod19940417

Solution


3西

f[i]irt.f[i]=ij=0ls.f[j]?rs.f[i?j]

f[0]=1

kf[i]ij=0f[j]?Cin?j?ki?j(想一想为什么)

c

reverseadd线

Code

#include <bits/stdc++.h>
using namespace std;
typedef long long LL;
#define ls (rt << 1)
#define rs (rt << 1 | 1)
const int N = 60050, M = 19940417;
int a[N], b[25], c[N][25], add[N << 2], rev[N << 2];
struct node {
    int f[25];
}p[N << 2];
inline int read(int &t) {
    int f = 1;char c;
    while (c = getchar(), c < ‘0‘ || c > ‘9‘) if (c == ‘-‘) f = -1;
    t = c - ‘0‘;
    while (c = getchar(), c >= ‘0‘ && c <= ‘9‘) t = t * 10 + c - ‘0‘;
    t *= f;
}
inline void U(int &x, int y) {
    x += y;
    if (x >= M) x -= M;
    if (x < 0)  x += M;
}
void calc(int rt, int l, int r, int x) {
    for (int i = 1; i <= 20; ++i) {
        int t = 0, tx = 1;
        for (int j = i; j >= 0; --j) {
            U(t, (LL)p[rt].f[j] * c[r - l + 1 - j][i - j] % M * tx % M);
            tx = (LL)tx * x % M;
        }
        b[i] = t;
    }   
    for (int i = 1; i <= 20; ++i)   p[rt].f[i] = b[i];
}
void down(int rt, int l, int r) {
    if (rev[rt]) {
        rev[ls] ^= 1, rev[rs] ^= 1;
        for (int i = 1; i <= 20; i += 2)    p[ls].f[i] = (M - p[ls].f[i]) % M;
        for (int i = 1; i <= 20; i += 2)    p[rs].f[i] = (M - p[rs].f[i]) % M;
        add[ls] = (M - add[ls]) % M, add[rs] = (M - add[rs]) % M;
        rev[rt] = 0;
    }
    if (add[rt]) {
        int mid = l + r >> 1;
        U(add[ls], add[rt]), U(add[rs], add[rt]);
        calc(ls, l, mid, add[rt]), calc(rs, mid + 1, r, add[rt]);
        add[rt] = 0;
    }
} 
void up(int rt) {
    for (int i = 1; i <= 20; ++i)   p[rt].f[i] = 0;
    for (int i = 0; i <= 20; ++i)   
        for (int j = 0; i + j <= 20; ++j) {
            if (i + j == 0) continue;
            U(p[rt].f[i + j], (LL)p[ls].f[i] * p[rs].f[j] % M);
        }
}
void build(int rt, int l, int r) {
    p[rt].f[0] = 1;
    if (l == r) {
        p[rt].f[1] = a[l];
        return;
    }
    int mid = l + r >> 1;
    build(ls, l, mid), build(rs, mid + 1, r);
    up(rt);
}
void reverse(int rt, int l, int r, int L, int R) {
    if (L <= l && R >= r) {
        rev[rt] ^= 1;
        add[rt] = (M - add[rt]) % M;
        for (int i = 1; i <= 20; i += 2) p[rt].f[i] = (M - p[rt].f[i]) % M;
        return;
    }
    down(rt, l, r);
    int mid = l + r >> 1;
    if (L <= mid)   reverse(ls, l, mid, L, R);
    if (R > mid)    reverse(rs, mid + 1, r, L, R);
    up(rt);
}
void inc(int rt, int l, int r, int L, int R, int x) {
    if (L <= l && R >= r) {
        U(add[rt], x);
        calc(rt, l, r, x);
        return;
    }
    int mid = l + r >> 1;
    down(rt, l, r);
    if (L <= mid)   inc(ls, l, mid, L, R, x);
    if (R > mid)    inc(rs, mid + 1, r, L, R, x);
    up(rt);
}
node ask(int rt, int l, int r, int L, int R) {
    if (L <= l && R >= r) {
        return p[rt];
    }
    down(rt, l, r);
    int mid = l + r >> 1;
    node t, t1, t2;
    if (L > mid)    t = ask(rs, mid + 1, r, L, R);
    else if (R <= mid)  t = ask(ls, l, mid, L, R);
    else {
        t.f[0] = 1;
        for (int i = 1; i <= 20; ++i)   t.f[i] = 0;
        t1 = ask(ls, l, mid, L, mid), t2 = ask(rs, mid + 1, r, mid + 1, R);
        for (int i = 0; i <= 20; ++i)
            for (int j = 0; j + i <= 20; ++j) {
                if (i + j == 0) continue;
                U(t.f[i + j], (LL)t1.f[i] * t2.f[j] % M);
            }
    }   
    return t;
}   
int main() {
    int n, q;
    read(n), read(q);
    for (int i = 0; i <= n; ++i) {
        c[i][0] = c[i][i] = 1;
        for (int j = 1; j < i; ++j) c[i][j] = (c[i - 1][j] + c[i - 1][j - 1]) % M;
    }
    for (int i = 1; i <= n; ++i)    read(a[i]), a[i] = (a[i] % M + M) % M;
    build(1, 1, n);
    char s[5];
    int x, y, z;
    while (q--) {
        scanf("%s", s);
        if (s[0] == ‘I‘) {
            read(x), read(y), read(z);
            z = (z % M + M) % M;
            inc(1, 1, n, x, y, z);
        }
        else if (s[0] == ‘R‘) {
            read(x), read(y);
            reverse(1, 1, n, x, y);
        }
        else {
            read(x), read(y), read(z);
            z = (z % M + M) % M;
            node t = ask(1, 1, n, x, y);
            printf("%d\n", t.f[z] % M);
        }
    }
    return 0;
}

bzoj 2962 序列操作(线段树)

原文:http://blog.csdn.net/mlzmlz95/article/details/43890337

(0)
(0)
   
举报
评论 一句话评论(0
关于我们 - 联系我们 - 留言反馈 - 联系我们:wmxa8@hotmail.com
© 2014 bubuko.com 版权所有
打开技术之扣,分享程序人生!