hdu 4893 线段树+二分fib

来源:互联网 发布:淘宝强行退款 编辑:程序博客网 时间:2024/05/16 10:43

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

这道题题意很清楚~就是线段树的运用,其中的第三个操作,也就是将一个数转变为与这个数相邻最小fib数;

如果直接操作,因为操作次数很多,应该会TLE,我们可以在每个树节点上加个cover变量,如果等于1,那么表示这个区间里的数已经是fib数了,不需要再更改了,这样就避免时间的浪费;

标准模板转自:http://blog.csdn.net/u011932355/article/details/38276763;

表示,自己敲不是RE,就是TLE,比赛的时候RE了一下午;无解了;

#include <stdio.h>
    #include <string.h>
    #include <cmath>
    #include <iostream>
    typedef long long ll;
    using namespace std;
    
    const  int  maxn=55;
    struct node
    {
        int l,r,cover;
        __int64 sum;
    }data[400010];
    
    __int64 a[maxn+1];
    
    
    
    __int64 find_near(__int64 x)    //二分找fib数
    {
        int l,r,mid;
        l=1; r=maxn;
        if (x<0) return 1;
        while (l<=r)
        {
            mid=(l+r)/2;
            if (a[mid]==x) return a[mid];
            if (a[mid]<x) l=mid+1;
            else r=mid-1;
        }
        if (x-a[l-1]<=a[l]-x) return a[l-1];
        else return a[l];
    }
    
    
    void build(int l,int r,int k)
    {
        int mid;
        data[k].l=l;
        data[k].r=r;
        data[k].sum=0;
        data[k].cover=0;
        if (l==r) return ;
        mid=(l+r)/2;
    
        build(l,mid,k*2);
        build(mid+1,r,k*2+1);
    }
    
    void updata(int n,int x,int k)
    {
        int mid;
        if (data[k].l==n && data[k].r==n)
        {
            data[k].sum+=x;
            if (data[k].sum==find_near(data[k].sum)) data[k].cover=1;
            else data[k].cover=-1;
            return ;
        }
        mid=(data[k].l+data[k].r)/2;
    
        if (n<=mid) updata(n,x,k*2);
        else updata(n,x,k*2+1);
    
        data[k].sum=data[k*2].sum+data[k*2+1].sum;
        if (data[k*2].cover==data[k*2+1].cover) data[k].cover=data[k*2].cover;
        else data[k].cover=-1;
    
    }
    __int64 search(int l,int r,int k)
    {
        int mid;
        if (data[k].l==l && data[k].r==r)
            return data[k].sum;
    
        mid=(data[k].l+data[k].r)/2;
    
        if (r<=mid) return search(l,r,k*2);
        else if (l>mid) return search(l,r,k*2+1);
        else return search(l,mid,k*2)+search(mid+1,r,k*2+1);
    }
    
    void change(int l,int r,int k)
    {
        int mid;
        if (data[k].cover==1) return ;
    
        if (data[k].l==data[k].r)
        {
            data[k].sum=find_near(data[k].sum);
            data[k].cover=1;
            return ;
        }
    
        mid=(data[k].l+data[k].r)/2;
    
        if(r<=mid) change(l,r,k*2);
        else if (l>mid) change(l,r,k*2+1);
        else {change(l,mid,k*2); change(mid+1,r,k*2+1);}
    
        data[k].sum=data[k*2].sum+data[k*2+1].sum;
        if (data[k*2].cover==data[k*2+1].cover) data[k].cover=data[k*2].cover;
        else data[k].cover=0;
    }
    int main()
    {
        int n,m,op,b,c,i;
    
        a[0]=a[1]=1;
        for (i=2;i<=maxn;i++)
            a[i]=a[i-1]+a[i-2];
        while (scanf("%d%d",&n,&m)!=EOF)
        {
            build(1,n,1);
            while (m--)
            {
                scanf("%d%d%d",&op,&b,&c);
                if (op==1) updata(b,c,1);
                if (op==2) printf("%I64d\n",search(b,c,1));
                if (op==3) change(b,c,1);
            }
        }
        return 0;
    }


0 0
原创粉丝点击