zoukankan      html  css  js  c++  java
  • HDU4893【线段树单点、区间更新】

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

    题意:输入n、q。表示有n个数,初始化默认这n个数都为零,有q次操作,操作种类分为三种:1、输入k,d,使得k位置的数加上d。2、输入l,r,求区间[l,r]的和并输出。3、输入l,r,把区间[l,r]内的数都改成斐波拉契数,修改方式为使得fabs[x-F[i]]最小,如果有多个F[i]满足情况,用最小的那个F[i]。1 ≤ n ≤ 100000, 1 ≤ m ≤ 100000, |d| < 231。

    题解:对于前两种操作,可以用单点更新来维护,但是对于第三种操作如果用单点更新的话,会TLE(n^2),所以我们要区间更新,我们要很快的知道区间[l,r]区间的FIB和,索性我们就在线段树里维护所有数的FIB和,在build,和操作一的时候更新就可以了。时间复杂度n*log(n)。

    #include<bits/stdc++.h>
    using namespace std;
    typedef long long LL;
    const int maxn = 100050;
    int n, m;
    struct node
    {
        int l, r;
        LL sm1, sm2;
        bool t;
    } T[maxn << 2];
    LL F[150];
    void init()
    {
        F[0] = F[1] = 1;
        for(int i = 2; i <= 90; i++)
            F[i] = F[i - 1] + F[i - 2];
    }
    LL FBI(LL x)
    {
        int pos = (int)(lower_bound(F, F + 80, x) - F);
        if(!pos) return F[0];
        else
        {
            LL t1 = F[pos] - x;
            LL t2 = x - F[pos - 1];
            if(t1 < t2)
                return F[pos];
            else
                return F[pos - 1];
        }
    }
    void pushup(int id)
    {
        T[id].sm1 = T[id << 1].sm1 + T[id << 1 | 1].sm1;
        T[id].sm2 = T[id << 1].sm2 + T[id << 1 | 1].sm2;
    }
    void pushdown(int id)
    {
        if(T[id].t)
        {
            T[id << 1].sm1 = T[id << 1].sm2;
            T[id << 1].t = 1;
            T[id << 1 | 1].sm1 = T[id << 1 | 1].sm2;
            T[id << 1 | 1].t = 1;
            T[id].t = 0;
        }
    }
    void build(int id, int l, int r)
    {
        T[id].l = l;
        T[id].r = r;
        T[id].t = 0;
        if(l == r)
        {
            T[id].sm1 = 0;
            T[id].sm2 = 1;
            return ;
        }
        else
        {
            int mid = (l + r) >> 1;
            build(id << 1, l, mid);
            build(id << 1 | 1, mid + 1, r);
            pushup(id);
        }
    }
    LL sum(int id, int l, int r)
    {
        if(T[id].l == l && T[id].r == r)
            return T[id].sm1;
        else
        {
            pushdown(id);
            int mid = (T[id].l + T[id].r) >> 1;
            if(r <= mid)
                return sum(id << 1, l, r);
            else if(l >= mid + 1)
                return sum(id << 1 | 1, l, r);
            else
                return sum(id << 1, l, mid) + sum(id << 1 | 1, mid + 1, r);
        }
    }
    void change(int id, int l, int r)
    {
        if(T[id].l == l && T[id].r == r)
        {
            T[id].sm1 = T[id].sm2;
            T[id].t = 1;
            return ;
        }
        else
        {
            pushdown(id);
            int mid = (T[id].l + T[id].r) >> 1;
            if(r <= mid)
            {
                change(id << 1, l, r);
            }
            else if(l >= mid + 1)
            {
                change(id << 1 | 1, l, r);
            }
            else
            {
                change(id << 1, l, mid);
                change(id << 1 | 1, mid + 1, r);
            }
            pushup(id);
        }
    }
    void update(int id, int pos, LL d)
    {
        if(T[id].l == T[id].r)
        {
            T[id].sm1 += d;
            T[id].sm2 = FBI(T[id].sm1);
            return ;
        }
        else
        {
            pushdown(id);
            int mid = (T[id].l + T[id].r) >> 1;
            if(pos <= mid)
                update(id << 1, pos, d);
            else
                update(id << 1 | 1, pos, d);
            pushup(id);
        }
    }
    int main()
    {
        init();
        while(scanf("%d%d", &n, &m) != EOF)
        {
            build(1, 1, n);//
            LL d;
            int k, l, r, ty;
            for(int i = 1; i <= m; i++)
            {
                scanf("%d", &ty);
                if(ty == 1)
                {
                    scanf("%d%lld", &k, &d);
                    update(1, k, d);
                }
                else if(ty == 2)
                {
                    scanf("%d%d", &l, &r);
                    printf("%lld
    ", sum(1, l, r));
                }
                else
                {
                    scanf("%d%d", &l, &r);
                    change(1, l, r);
                }
            }
        }
        return 0;
    }
    想的太多,做的太少。
  • 相关阅读:
    jacman主题分页出现问题(Next<span></span>)
    后会有期(非技术)
    再谈前端性能优化
    emmet常用指令组合
    imagemagick在windows下安装(转,有改动)
    nth-child和蝉原则实现的奇妙随机效果(译)
    flex布局浅谈和实例
    css命名那些事儿
    chrome开发者工具浅析--timeline
    浏览器历史和发展趋势浅析
  • 原文地址:https://www.cnblogs.com/pealicx/p/6422444.html
Copyright © 2011-2022 走看看