线段树结点上保存一个一般的sum值,再同时保存一个fbsum,表示这个结点表示的一段数字若为斐波那契数时的和
当进行3操作时,只用将sum = fbsum即可
其他操作照常进行,只是单点更新的时候也要先向下更新
#include <cstdio> #include <ctime> #include <cstdlib> #include <cstring> #include <queue> #include <string> #include <set> #include <stack> #include <map> #include <cmath> #include <vector> #include <iostream> #include <algorithm> #include <bitset> #include <fstream> using namespace std; //LOOP #define FF(i, a, b) for(int i = (a); i < (b); ++i) #define FE(i, a, b) for(int i = (a); i <= (b); ++i) #define FED(i, b, a) for(int i = (b); i>= (a); --i) #define REP(i, N) for(int i = 0; i < (N); ++i) #define CLR(A,value) memset(A,value,sizeof(A)) #define FC(it, c) for(__typeof((c).begin()) it = (c).begin(); it != (c).end(); it++) //OTHER #define SZ(V) (int)V.size() #define PB push_back #define MP make_pair #define all(x) (x).begin(),(x).end() //INPUT #define RI(n) scanf("%d", &n) #define RII(n, m) scanf("%d%d", &n, &m) #define RIII(n, m, k) scanf("%d%d%d", &n, &m, &k) #define RIV(n, m, k, p) scanf("%d%d%d%d", &n, &m, &k, &p) #define RV(n, m, k, p, q) scanf("%d%d%d%d%d", &n, &m, &k, &p, &q) #define RS(s) scanf("%s", s) //OUTPUT #define WI(n) printf("%d\n", n) #define WS(n) printf("%s\n", n) #define sqr(x) (x) * (x) typedef long long LL; typedef unsigned long long ULL; typedef vector <int> VI; const double eps = 1e-9; const int MOD = 1000000007; const double PI = acos(-1.0); //const int INF = 0x3f3f3f3f; const int maxn = 100010; const LL INF = 0x3f3f3f3f3f3f3f3fLL; #define ll rt << 1 #define rr rt << 1 | 1 struct Node{ int l, r, m; LL sum, fbsum; bool f; }t[maxn * 4]; LL fb[10000]; int fbcnt; void init() { fb[1] = 1, fb[0] = 1; for (int i = 2; ; i++) { fb[i] = fb[i - 1] + fb[i - 2]; if (fb[i] > INF) { fbcnt = i - 1; return; } } return; } void push_up(int rt) { t[rt].sum = t[ll].sum + t[rr].sum; t[rt].fbsum = t[ll].fbsum + t[rr].fbsum; t[rt].f = t[ll].f & t[rr].f; } LL get(LL x) { int pos = lower_bound(fb, fb + fbcnt, x) - fb; if (pos && abs(fb[pos - 1] - x) <= abs(fb[pos] - x)) return fb[pos - 1]; return fb[pos]; } void push_down(int rt) { if (t[rt].f) { t[ll].sum = t[ll].fbsum; t[rr].sum = t[rr].fbsum; t[rr].f = t[ll].f = 1; t[rt].f = 0; } } void build(int l, int r, int rt) { t[rt].l = l, t[rt].r = r, t[rt].m = (l + r) >> 1; if (l == r) { t[rt].sum = 0; t[rt].fbsum = 1; t[rt].f = 0; return; } build(l, t[rt].m, ll); build(t[rt].m + 1, r, rr); push_up(rt); } void update(int x, int add, int rt) { if (x == t[rt].l && t[rt].r == x) { t[rt].sum += add; t[rt].fbsum = get(t[rt].sum); t[rt].f = 0; return; } push_down(rt); if (x <= t[rt].m) update(x, add, ll); else update(x, add, rr); push_up(rt); } void updatefb(int l, int r, int rt) { if (l <= t[rt].l && r >= t[rt].r) { t[rt].sum = t[rt].fbsum; t[rt].f = 1; return; } push_down(rt); if (l <= t[rt].m) updatefb(l, r, ll); if (r > t[rt].m) updatefb(l, r, rr); push_up(rt); } LL query(int l, int r, int rt) { if (l <= t[rt].l && r >= t[rt].r) return t[rt].sum; push_down(rt); LL ans = 0; if (l <= t[rt].m) ans += query(l, r, ll); if (r > t[rt].m) ans += query(l, r, rr); return ans; } int main() { init(); int n, m; while (~RII(n, m)) { build(1, n, 1); int x, y, op; while (m--) { RIII(op, x, y); if (op == 1) update(x, y, 1); else if (op == 2) printf("%I64d\n", query(x, y, 1)); else updatefb(x, y, 1); } } return 0; } /* 5 4 3 1 3 2 1 3 1 3 3 2 1 3 5 2 3 1 3 2 1 2 */
hdu4893 Wow! Such Sequence!
时间: 2024-11-03 13:30:06