首页 > 代码库 > HDOJ--4893--Wow! Such Sequence!【线段树+单点、区间更新】

HDOJ--4893--Wow! Such Sequence!【线段树+单点、区间更新】

链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893

题意:给你一个长度n的数列,初始都为0。有三种操作,第一种给第k个位置的数加d。另外一种是查询区间 [l , r] 的总和。第三种是使区间 [l , r] 的值改为离它近期的那个斐波那契数的值。


我刚開始用sum数组存储节点的值。第三种操作是个区间更新,可是区间更新的值不一样。我就想当然的搜到最底部的节点来处理更新,果断T了。后来想了想。事实上能够在节点上再加一个信息。就是这个值下次进行第三种操作要变成的值,在每次进行第一种操作时进行这个值得更新,区间也一样存储下次变化后的总值。这样在进行第三种操作时就能够进行区间更新了比較省时。我不习惯用结构体写,所以多定义了一个数组。


sum数组存储正常值。fuck数组存储下次要变成的斐波那契值。col数组仅仅起标记作用。

事实上这题就是简单的单点更新和区间更新,合到了一起,我还是做的太少。没有在单点更新和区间查询中加pushdown,WA了两发。


#include<cstring>
#include<string>
#include<fstream>
#include<iostream>
#include<iomanip>
#include<cstdio>
#include<cctype>
#include<algorithm>
#include<queue>
#include<map>
#include<set>
#include<vector>
#include<stack>
#include<ctime>
#include<cstdlib>
#include<functional>
#include<cmath>
using namespace std;
#define PI acos(-1.0)
#define MAXN 100100
#define eps 1e-11
#define INF 0x7FFFFFFF
#define lson l,m,rt<<1
#define rson m+1,r,rt<<1|1

long long sum[MAXN<<2];
long long col[MAXN<<2];
long long fuck[MAXN<<2];
long long n,m;
long long f[100];
void pushup(long long rt){
    sum[rt] = sum[rt<<1] + sum[rt<<1|1];
    fuck[rt] = fuck[rt<<1] + fuck[rt<<1|1];
}
void pushdown(long long rt,long long m){
    if(col[rt]){
        col[rt<<1] = fuck[rt<<1];
        col[rt<<1|1] = fuck[rt<<1|1];
        sum[rt<<1] = fuck[rt<<1];
        sum[rt<<1|1] = fuck[rt<<1|1];
        col[rt] = 0;
    }
}
void build(long long l,long long r,long long rt){
    col[rt] = 0;
    if(l==r){
        sum[rt] = 0;
        fuck[rt] = 1;
        return ;
    }
    long long m = (l+r)>>1;
    build(lson);
    build(rson);
    pushup(rt);
}
void update(long long pos,long long add,long long l,long long r,long long rt){
    if(l==r){
        sum[rt] += add;
        long long p = lower_bound(f,f+90,sum[rt])-f;
        if(p-1>=0){
            long long fp1 = f[p] - sum[rt];
            if(fp1<0)   fp1 = -fp1;
            long long fp2 = f[p-1] - sum[rt];
            if(fp2<0)   fp2 = -fp2;
            if(fp1>=fp2)   fuck[rt] = f[p-1];
            else    fuck[rt] = f[p];
        }
        else    fuck[rt] = f[p];
        return ;
    }
    pushdown(rt,r-l+1);
    long long m = (l+r)>>1;
    if(pos<=m)  update(pos,add,lson);
    else    update(pos,add,rson);
    pushup(rt);
}
void update2(long long L,long long R,long long l,long long r,long long rt){
    if(L<=l&&r<=R){
        col[rt] = fuck[rt];
        sum[rt] = fuck[rt];
        return ;
    }
    pushdown(rt,r-l+1);
    long long m = (l+r)>>1;
    if(L<=m)    update2(L,R,lson);
    if(R>m)     update2(L,R,rson);
    pushup(rt);
}
long long query(long long L,long long R,long long l,long long r,long long rt){
    if(L<=l&&r<=R){
        return sum[rt];
    }
    pushdown(rt,rt-l+1);
    long long ans = 0;
    long long m = (l+r)>>1;
    if(L<=m)    ans += query(L,R,lson);
    if(R>m)     ans += query(L,R,rson);
    return ans;
}
int main(){
    long long i,j,l,r,k,d,x;
    f[0] = 1;
    f[1] = 1;
    for(i=2;i<90;i++){
        f[i] = f[i-1] + f[i-2];
    }
    while(scanf("%I64d%I64d",&n,&m)!=EOF){
        build(1,n,1);
        while(m--){
            scanf("%I64d%I64d%I64d",&x,&l,&r);
            if(x==1){
                update(l,r,1,n,1);
            }
            else if(x==2){
                long long ans = query(l,r,1,n,1);
                printf("%I64d\n",ans);
            }
            else{
                update2(l,r,1,n,1);
            }
        }
    }
    return 0;
}


HDOJ--4893--Wow! Such Sequence!【线段树+单点、区间更新】