题意是这样的,给定一个n个元素的数组,初始值为0,3种操作:
1 k d将第k个数增加d;
2 l r 询问区间l...r范围内数之和;
3 l r 表示将区间l...r内的数变成离他最近的斐波那契数,要求尽量小。
线段树操作题目,其中对于第三种操作用一个懒惰标记一下,表示l...r内的数是不是已经变成斐波那契数,如果是的话,求和就是其相应数的斐波那契数之和。
代码:
1 //Template updates date: 20140718 2 #include <bits/stdc++.h> 3 #define esp 1e-6 4 #define inf 0x3f3f3f3f 5 #define pi acos(-1.0) 6 #define pb push_back 7 #define lson l, m, rt<<1 8 #define rson m+1, r, rt<<1|1 9 #define lowbit(x) (x&(-x)) 10 #define mp(a, b) make_pair((a), (b)) 11 #define bit(k) (1<<(k)) 12 #define iin freopen("pow.in", "r", stdin); 13 #define oout freopen("pow.out", "w", stdout); 14 #define in freopen("solve_in.txt", "r", stdin); 15 #define out freopen("solve_out.txt", "w", stdout); 16 #define bug puts("********))))))"); 17 #define Inout iin oout 18 #define inout in out 19 20 #define SET(a, v) memset(a, (v), sizeof(a)) 21 #define SORT(a) sort((a).begin(), (a).end()) 22 #define REV(a) reverse((a).begin(), (a).end()) 23 #define READ(a, n) {REP(i, n) cin>>(a)[i];} 24 #define REP(i, n) for(int i = 0; i < (n); i++) 25 #define VREP(i, n, base) for(int i = (n); i >= (base); i--) 26 #define Rep(i, base, n) for(int i = (base); i < (n); i++) 27 #define REPS(s, i) for(int i = 0; (s)[i]; i++) 28 #define pf(x) ((x)*(x)) 29 #define mod(n) ((n)) 30 #define Log(a, b) (log((double)b)/log((double)a)) 31 #define Srand() srand((int)time(0)) 32 #define random(number) (rand()%number) 33 #define random_range(a, b) (int)(((double)rand()/RAND_MAX)*(b-a) + a) 34 35 using namespace std; 36 typedef long long LL; 37 typedef unsigned long long ULL; 38 typedef vector<int> VI; 39 typedef pair<int,int> PII; 40 typedef vector<PII> VII; 41 typedef vector<PII, int> VIII; 42 typedef VI:: iterator IT; 43 typedef map<string, int> Mps; 44 typedef map<int, int> Mpi; 45 typedef map<int, PII> Mpii; 46 typedef map<PII, int> Mpiii; 47 const int maxm = 140000 + 1000; 48 49 LL f[92]; 50 int n, m; 51 LL sum[maxm<<2], sum1[maxm<<2], cover[maxm<<2]; 52 53 void pre() { 54 f[0] = f[1] = 1; 55 Rep(i, 2, 92) { 56 f[i] = f[i-1] + f[i-2]; 57 } 58 } 59 void PushDown(int rt) { 60 if(cover[rt]) { 61 cover[rt] = 0; 62 cover[rt<<1] = cover[rt<<1|1] = 1; 63 sum[rt<<1] = sum1[rt<<1]; 64 sum[rt<<1|1] = sum1[rt<<1|1]; 65 } 66 } 67 void PushUp(int rt) { 68 sum[rt] = sum[rt<<1]+sum[rt<<1|1]; 69 sum1[rt] = sum1[rt<<1]+sum1[rt<<1|1]; 70 } 71 void build(int l, int r, int rt) { 72 if(l == r) { 73 sum[rt] = 0; 74 sum1[rt] = 1; 75 cover[rt] = 0; 76 return ; 77 } 78 int m = (l+r)>>1; 79 build(lson); 80 build(rson); 81 PushUp(rt); 82 cover[rt] = 0; 83 } 84 85 void update(int l, int r, int rt, int k, int d) { 86 if(l == k && r == k) { 87 sum[rt] += d; 88 int b = upper_bound(f+1, f+92, sum[rt]) - f; 89 if(abs(f[b]-sum[rt]) >= abs(f[b-1]-sum[rt])) 90 sum1[rt] = f[b-1]; 91 else 92 sum1[rt] = f[b]; 93 return; 94 } 95 PushDown(rt); 96 int m = (l+r)>>1; 97 if(k <= m) 98 update(lson, k, d); 99 else update(rson, k, d); 100 PushUp(rt); 101 } 102 void update1(int L, int R, int l, int r, int rt) { 103 if(L <=l && R >= r) { 104 cover[rt] = 1; 105 sum[rt] = sum1[rt]; 106 return; 107 } 108 PushDown(rt); 109 int m = (l+r)>>1; 110 if(L <= m) 111 update1(L, R, lson); 112 if(R > m) 113 update1(L, R, rson); 114 PushUp(rt); 115 } 116 LL query(int L, int R, int l, int r, int rt) { 117 if(L <= l && R >= r) { 118 return sum[rt]; 119 } 120 int m = (l+r)>>1; 121 PushDown(rt); 122 LL ans = 0; 123 if(L <= m) 124 ans += query(L, R, lson); 125 if( R > m) 126 ans += query(L, R, rson); 127 return ans; 128 } 129 int main() { 130 131 pre(); 132 while(scanf("%d%d", &n, &m) == 2) { 133 build(1, n, 1); 134 REP(i, m) { 135 int u, l, r; 136 scanf("%d%d%d", &u, &l, &r); 137 if(u == 2) { 138 printf("%I64d ", query(l, r, 1, n, 1)); 139 } else if(u == 1) { 140 update(1, n, 1, l, r); 141 } else { 142 update1(l, r, 1, n, 1); 143 } 144 } 145 } 146 return 0; 147 }