HDU 4893 - Wow! Such Sequence!(線段樹)

題意:給定 n 個數的序列(1 <= n <= 100000,且初始均爲 0),m 個操做(1 <= m <= 100000),操做共分三種:ios

一、將第 k 個數加 d;數組

二、求 l 到 r 區間和;函數

三、將 l 到 r 區間內的數,各自變爲距離各自最近的斐波那契數(若是有兩個數同樣近,則取小的斐波那契數).spa

 

有區間求和區間修改還有點修改,很明顯的一個線段樹的題;code

先將斐波那契數打表,而後每次查找時用 lower_bound 二分查找;blog

須要一個 sum 數組用來求和,寫兩個 update 函數分別爲某個點數值增長以及區間修改爲斐波那契;get

爲了防止超時,還須要增長一個「判斷區間是否已經成爲斐波那契數」的判斷數組.string

代碼以下:it

#pragma comment(linker, "/STACK:102400000, 102400000")
#include<cstdio>
#include<cstring>
#include<cctype>
#include<cstdlib>
#include<cmath>
#include<iostream>
#include<sstream>
#include<iterator>
#include<algorithm>
#include<string>
#include<vector>
#include<set>
#include<map>
#include<deque>
#include<queue>
#include<stack>
#include<list>
#define fin freopen("in.txt", "r", stdin)
#define fout freopen("out.txt", "w", stdout)
#define pr(x) cout << #x << " : " << x << "   "
#define prln(x) cout << #x << " : " << x << endl
#define Min(a, b) a < b ? a : b
#define Max(a, b) a < b ? b : a
typedef long long ll;
typedef unsigned long long llu;
const int INT_INF = 0x3f3f3f3f;
const int INT_M_INF = 0x7f7f7f7f;
const ll LL_INF = 0x3f3f3f3f3f3f3f3f;
const ll LL_M_INF = 0x7f7f7f7f7f7f7f7f;
const double pi = acos(-1.0);
const double EPS = 1e-8;
const int dr[] = {0, 0, -1, 1, -1, -1, 1, 1};
const int dc[] = {-1, 1, 0, 0, -1, 1, -1, 1};
const ll MOD = 1e9 + 7;
using namespace std;

#define NDEBUG
#include<cassert>
const int MAXN = 75 + 10;
const int MAXT = 100000 + 10;

ll fib[MAXN << 2];

void init(){
    fib[0] = 1;  fib[1] = 2;
    for(int i = 2; i < MAXN; ++i)  fib[i] = fib[i - 1] + fib[i - 2];
}

ll sum[MAXT << 2];
bool flag[MAXT << 2];

ll getfib(ll value){
    int lur = lower_bound(fib, fib + MAXN, value) - fib;
    ll one = abs(fib[lur] - value);
    ll two = lur > 0 ? abs(fib[lur - 1] - value) : one;
    if(one != two)  return one < two ? fib[lur] : fib[lur - 1];
    return lur > 0 ? fib[lur - 1] : fib[lur];
}

void PushUp(int lur){
    sum[lur] = sum[lur << 1] + sum[lur << 1 | 1];
    flag[lur] = flag[lur << 1] & flag[lur << 1 | 1];
}

void Update(int lur, int x, int l, int r, int id){
    if(l == r){
        sum[id] += x;
        flag[id] = false;
        return;
    }
    int mid = (l + r) >> 1;
    if(lur <= mid)  Update(lur, x, l, mid, id << 1);
    else  Update(lur, x, mid + 1, r, id << 1 | 1);
    PushUp(id);
}

void Update2(int L, int R, int l, int r, int id){
    if(flag[id])  return;
    if(l == r){
        sum[id] = getfib(sum[id]);
        flag[id] = true;
        return;
    }
    int mid = (l + r) >> 1;
    if(L <= mid)  Update2(L, R, l, mid, id << 1);
    if(mid < R)  Update2(L, R, mid + 1, r, id << 1 | 1);
    PushUp(id);
}

ll Query(int L, int R, int l, int r, int id){
    if(L <= l && r <= R){
        return sum[id];
    }
    int mid = (l + r) >> 1;
    ll ans = 0;
    if(L <= mid)  ans += Query(L, R, l, mid, id << 1);
    if(mid < R)  ans += Query(L, R, mid + 1, r, id << 1 | 1);
    return ans;
}

int main(){
    init();
    int n, m;
    while(scanf("%d%d", &n, &m) == 2){
        memset(sum, 0, sizeof sum);
        memset(flag, false, sizeof flag);
        while(m--){
            int o;  scanf("%d", &o);
            if(o == 1){
                int k;  int d;
                scanf("%d%d", &k, &d);
                Update(k, d, 1, n, 1);
            }
            else if(o == 2){
                int l, r;
                scanf("%d%d", &l, &r);
                printf("%I64d\n", Query(l, r, 1, n, 1));
            }
            else{
                int l, r;
                scanf("%d%d", &l, &r);
                Update2(l, r, 1, n, 1);
            }
        }
    }
    return 0;
}
相關文章
相關標籤/搜索