Codeforces Round #FF (Div. 2)__E. DZY Loves Fibonacci Numbers (CF447) 线段树

http://codeforces.com/contest/447/problem/E

题意: 给定一个数组, m次操作,

1 l r 表示区间修改, 每次 a[i] +  Fibonacci[i-l+] 

2 l r 区间求和

每次修改操作,只需要记录 每个点前两个值就可以了, 后面的和以及孩子需要加的值都可以通过这两个求出来。 推推公式就出来了。

注意 溢出。

  1 #include <bits/stdc++.h>

  2 using namespace std;

  3 typedef long long LL;

  4 const int MAXN = 3e5+10;

  5 const int MOD = 1e9+9;

  6 LL sum[MAXN << 2], addv1[MAXN << 2], addv2[MAXN << 2];

  7 LL fib[MAXN], hhh[MAXN], fff[MAXN];

  8 void pre_solve() {

  9     fff[1] = 1;

 10     fff[2] = 0;

 11     fib[1] = fib[2] = 1;

 12     hhh[1] = 0;

 13     for (int i = 3; i < MAXN; i++) {

 14         fib[i] = (fib[i-1] + fib[i-2]) % MOD;

 15         fff[i] = (fff[i-1] + fff[i-2]) % MOD;

 16     }

 17     for (int i = 2; i < MAXN; i++) {

 18         hhh[i] = (fib[i-1] + hhh[i-1]) % MOD;

 19     }

 20 }

 21 void push_up(int pos) {

 22     sum[pos] = (sum[pos<<1] + sum[pos<<1|1]) % MOD;

 23 }

 24 void update_add(int l, int r, int pos, LL val1, LL val2) {

 25     addv1[pos] = (addv1[pos] + val1) % MOD;

 26     addv2[pos] = (addv2[pos] + val2) % MOD;

 27     int idx = (r - l + 1);

 28     sum[pos] = (sum[pos] + fib[idx] * val1 % MOD + hhh[idx] * val2 % MOD) % MOD;

 29 }

 30 void push_down(int l, int r, int pos) {

 31     int mid = (l + r) >> 1;

 32     update_add(l, mid, pos<<1, addv1[pos], addv2[pos]);

 33     update_add(mid+1, r, pos<<1|1, (fff[mid+1-l+1]*addv1[pos]+fib[mid+1-l]*addv2[pos])%MOD,

 34                (fff[mid+1-l+2]*addv1[pos]+fib[mid+1-l+1]*addv2[pos])%MOD);

 35     addv1[pos] = addv2[pos] = 0;

 36 }

 37 void build (int l, int r, int pos) {

 38     addv1[pos] = addv2[pos] = 0;

 39     if (l == r) {

 40         scanf ("%I64d", sum+pos);

 41         return ;

 42     }

 43     int mid = (l + r) >> 1;

 44     build(l, mid, pos<<1);

 45     build(mid+1, r, pos<<1|1);

 46     push_up(pos);

 47 }

 48 void update (int l, int r, int pos, int ua, int ub, LL x1, LL x2) {

 49     if (ua <= l && ub >= r) {

 50         update_add(l, r, pos, x1, x2);

 51         return ;

 52     }

 53     push_down(l, r, pos);

 54     int mid = (l + r) >> 1;

 55     if (ua <= mid) {

 56         update(l, mid, pos<<1, ua, ub, x1, x2);

 57     }

 58     if (ub > mid) {

 59         if (ua <= mid) {

 60             int tmp = max(l, ua);

 61             LL t1 = (fff[mid+1-tmp+1]*x1+fib[mid+1-tmp]*x2) % MOD;

 62             LL t2 = (fff[mid+1-tmp+2]*x1+fib[mid+1-tmp+1]*x2) % MOD;

 63             update(mid+1, r, pos<<1|1, ua, ub, t1, t2);

 64         } else {

 65             update(mid+1, r, pos<<1|1, ua, ub, x1, x2);

 66         }

 67     }

 68     push_up(pos);

 69 }

 70 LL query (int l, int r, int pos, int ua, int ub) {

 71     if (ua <= l && ub >= r) {

 72         return sum[pos];

 73     }

 74     push_down(l, r, pos);

 75     int mid = (l + r) >> 1;

 76     LL tmp = 0;

 77     if (ua <= mid)

 78     {

 79         tmp = (tmp + query(l, mid, pos<<1, ua, ub)) % MOD;

 80     }

 81     if (ub > mid)

 82     {

 83         tmp = (tmp + query(mid+1, r, pos<<1|1, ua, ub)) % MOD;

 84     }

 85 

 86     return tmp;

 87 }

 88 int main() {

 89 #ifndef ONLINE_JUDGE

 90     freopen("in.txt","r",stdin);

 91 #endif

 92     int n, m;

 93     pre_solve();

 94     while (~ scanf ("%d%d", &n, &m)) {

 95         build(1, n, 1);

 96         for (int i = 0; i < m; i++) {

 97             int op, u, v;

 98             scanf ("%d%d%d", &op, &u, &v);

 99             if (op == 1) {

100                 update(1, n, 1, u, v, fib[1], fib[2]);

101             } else {

102                 LL ans = query(1, n, 1, u, v);

103                 printf("%I64d\n", ans);

104             }

105         }

106     }

107     return 0;

108 }

 

你可能感兴趣的:(codeforces)