1. 程式人生 > >hdu 4893 Wow! Such Sequence! (線段樹 區間更新+單點更新)

hdu 4893 Wow! Such Sequence! (線段樹 區間更新+單點更新)

/*
1 k d 第k個數加d
2 l r 查詢l到r的和
3 l r l到r更新到最近的f[]
*/
# include <stdio.h>
# include <algorithm>
# include <string.h>
using namespace std;
# define lson l,m,rt<<1
# define rson m+1,r,rt<<1|1
# define N 100005
__int64 sum[N<<2],need[N<<2],L[N<<2],R[N<<2];
__int64 f[110];
int col[N<<2];
__int64 find(__int64 x)//二分查詢最近f[]
{
    if(x<=1)
        return 1;
    int left=1;
    int right=93;
    while(left<=right)
    {
        int mid=(left+right)>>1;
        if(f[mid]-x>0)
            right=mid-1;
        else
            left=mid+1;
    }
    // printf("%I64d %I64d\n",f[left],f[left-1]);
    //int left=lower_bound(f,f+93,x)-f;
    if(f[left]-x>=x-f[left-1])
        return f[left-1];
    return f[left];
}
void PushUP(int rt)
{
    sum[rt]=sum[rt<<1]+sum[rt<<1|1];
    need[rt]=need[rt<<1]+need[rt<<1|1];
}
void PushDown(int rt)
{
    if(col[rt]!=-1)
    {
        col[rt<<1]=col[rt<<1|1]=1;
        sum[rt<<1]+=need[rt<<1];
        sum[rt<<1|1]+=need[rt<<1|1];
        need[rt<<1|1]=need[rt<<1]=0;
        col[rt]=-1;
    }
}
void build(int l,int r,int rt)
{
    col[rt]=-1;
    sum[rt]=0;
    if(l==r)
    {
        need[rt]=1;//如果沒有更新過 原來是0所以最小需要1到底f[]
        return ;
    }
    int m=(l+r)>>1;
    build(lson);
    build(rson);
    PushUP(rt);
}
void add(int a,int val,int l,int r,int rt)//單點更新
{
    if(l==r)
    {
        sum[rt]+=val;
        col[rt]=1;
        need[rt]=find(sum[rt])-sum[rt];
        return ;
    }
    PushDown(rt);
    int m=(l+r)>>1;
    if(a<=m)
        add(a,val,lson);
    else
        add(a,val,rson);
    PushUP(rt);
}
void update(int a,int b,int l,int r,int rt)//區間更新為最近且最小的斐波那契數
{
    if(a<=l&&b>=r)
    {
        sum[rt]+=need[rt];
        col[rt]=1;
        need[rt]=0;
        return ;
    }
    PushDown(rt);
    int m=(l+r)>>1;
    if(a<=m)
        update(a,b,lson);
    if(b>m)
        update(a,b,rson);
    PushUP(rt);
}
__int64 query(int a,int b,int l,int r,int rt)
{
    if(a<=l&&b>=r)
    {
        return sum[rt];
    }
    PushDown(rt);
    __int64 ret=0;
    int m=(l+r)>>1;
    if(a<=m)
        ret+=query(a,b,lson);
    if(b>m)
        ret+=query(a,b,rson);
    return ret;
}
int main()
{
    f[0]=1;
    f[1]=1;
    for(int i=2; i<=93; i++)
    {
        f[i]=f[i-1]+f[i-2];
    }
    int n,m,op,b,c;
    while(~scanf("%d%d",&n,&m))
    {
        build(1,n,1);
        while(m--)
        {
            scanf("%d%d%d",&op,&b,&c);
            if(op==1)
            {
                add(b,c,1,n,1);
            }
            else if(op==2)
            {
                printf("%I64d\n",query(b,c,1,n,1));
            }
            else
            {
                update(b,c,1,n,1);
            }

        }
        // for(int i=1; i<=n; i++)
        //    printf("%I64d\n",query(i,i,1,n,1));
    }
    return 0;
}