zoukankan      html  css  js  c++  java
  • HDU 4893 2014多校三 线段树

    给定一个初始都为0的序列,有三种操作,前两种比较正常,一个是对某个位置的数add k,另一个是query区间和。然后比较麻烦的是第三个操作,把某个区间里面的每个值改成离它最近的Fibonacci数,如果存在左右两个离它近的,优先取左边数值小的

    一看到前两个操作马上就想上手敲树状数组,后来看到第三个就有点傻眼了,思维当时一直停留在怎么快速改值。。但忽略了题目本身要求什么,只有操作2才是输出,也就是只要求区间和值而且,其他两个都是操作而已,在聪哥的提醒下,知道对线段树开两个值记录+一个懒惰标记,一个值d记录正常的区间和值,另一个sf记录当前的fibanacci数值和

    懒惰标记记录当前区间是否被3操作过,若被标记了,下次query就是返回sf,否则返回d。

    不过一开始思路还是有点不清晰,还WA了几发。明显按上面的转化就是一个普通的单点更新+懒惰标记+区间查询的线段树了嘛

    主要错在pushdown函数和3操作处理上。没分清模块

    首先3操作命名为fix,fix找到对应的区间后,就进行懒惰标记,顺便把当前区间d改为sf值,然后向上传递。

    add操作,首先,找到最后单点即进行更新操作,否则pushdown,把懒惰标记传递下去,在标记里面也是要对d=sf操作的,最后向上传递结果

    query就更明显了,找区间return sf 或者 d,没找到就先pushdown

    一开始糊里糊涂,pushdown又没push好,还没修改当前的值

    比赛的时候还是有点糊里糊涂,线段树功底还不够,还要继续练

    #include <iostream>
    #include <cstdio>
    #include <cstring>
    #include <algorithm>
    #define lson rt<<1,l,mid
    #define rson rt<<1|1,mid+1,r
    #define LL __int64
    using namespace std;
    const int N = 100010;
    LL f[100];
    LL d[N<<2],flag[N<<2],sf[N<<2];
    LL pref[N];
    int n,q;
    void init()
    {
        LL tmp=1LL<<60;
        f[0]=f[1]=1;
        for (int i=2;i<=90;i++){
            f[i]=f[i-1]+f[i-2];
    
        }
    }
    
    void build(int rt ,int l,int r)
    {
        flag[rt]=d[rt]=0;
        if (l>=r){
            sf[rt]=1;
            return;
        }
        int mid=(l+r)>>1;
        build(lson);
        build(rson);
        sf[rt]=sf[rt<<1]+sf[rt<<1|1];
    }
    void change(int rt)
    {
        d[rt]=sf[rt];
    }
    void up(int rt,int l,int r)
    {
        d[rt]=d[rt<<1]+d[rt<<1|1];
        sf[rt]=sf[rt<<1]+sf[rt<<1|1];
    
    }
    void pushdown(int rt,int l,int r)
    {
        int mid=(l+r)>>1;
        if (flag[rt]==0 || l>=r) return;
        flag[rt<<1]=flag[rt<<1|1]=flag[rt];
        d[rt<<1]=sf[rt<<1];
        d[rt<<1|1]=sf[rt<<1|1];
        flag[rt]=0;
    }
    void fix(int L,int R,int rt,int l,int r)
    {
        if (flag[rt]==1) return;
        if (L<=l && r<=R){
            flag[rt]=1;
            d[rt]=sf[rt];
            return;
        }
        int mid=(l+r)>>1;
        if (R<=mid) fix(L,R,lson);
        else
        if (L>mid) fix(L,R,rson);
        else{
            fix(L,R,lson);
            fix(L,R,rson);
        }
        if (flag[rt<<1]==1 && flag[rt<<1|1]==1){
            flag[rt]=1;
        }
        up(rt,l,r);
    }
    void add(int loc,LL val,int rt,int l,int r)
    {
        if (l>=r)
        {
            flag[rt]=0;
            d[rt]+=val;
            int loc=lower_bound(f,f+90,d[rt])-f;
            sf[rt]=f[loc];
            if (loc>0){
                if (d[rt]-f[loc-1]<=f[loc]-d[rt]){
                sf[rt]=f[loc-1];
                }
            }
            return;
        }
        pushdown(rt,l,r);
        int mid=(l+r)>>1;
        if (loc<=mid) add(loc,val,lson);
        else add(loc,val,rson);
        up(rt,l,r);
    }
    
    LL query(int L,int R,int rt,int l,int r)
    {
        if (L<=l && r<=R){
            if (flag[rt]) return sf[rt];
            else return d[rt];
        }
        pushdown(rt,l,r);
        int mid=(l+r)>>1;
        if (R<=mid) return query(L,R,lson);
        else
        if (L>mid) return query(L,R,rson);
        else
        {
            LL ret1=query(L,R,lson);
            LL ret2=query(L,R,rson);
            return ret1+ret2;
        }
    }
    int main()
    {
        init();
        int op;
        while (scanf("%d%d",&n,&q)!=EOF)
        {
            build(1,1,n);
            while (q--)
            {
                scanf("%d",&op);
                if (op==1){
                    int a;
                    LL b;
                    scanf("%d%I64d",&a,&b);
                    add(a,b,1,1,n);
                }
                else
                if (op==2){
                    int a,b;
                    scanf("%d%d",&a,&b);
                    LL ans=query(a,b,1,1,n);
                    printf("%I64d
    ",ans);
                }
                else{
                    int a,b;
                    scanf("%d%d",&a,&b);
                    fix(a,b,1,1,n);
                }
            }
        }
        return 0;
    }
  • 相关阅读:
    AE二次开发,解决子窗体使用父窗体的AxControl控件
    ArcEngine二次开发中运行出现There is no Spatial Analyst license currently available or enabled.
    Js网站开发学习第一天
    Winform开发1
    MySql安装
    Windows ping加时间戳
    XML特性总结
    linux手册中函数名后小括号中数字的含义
    TCP通信
    swap交换分区概念
  • 原文地址:https://www.cnblogs.com/kkrisen/p/3876715.html
Copyright © 2011-2022 走看看