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!【线段树+单点、区间更新】,布布扣,bubuko.com

时间: 2024-10-05 05:05:51

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

HDOJ 4893 Wow! Such Sequence! 线段树

http://acm.hdu.edu.cn/showproblem.php?pid=4893 题意:10万的区间,初始都为0,10万次操作,三种操作为单点修改,区间将每个数改成最近的斐波那契数,以及区间求和. 分析:用一个flag记录该段是否被改成斐波那契数,同时多维护一个sum1表示如果该段改成斐波那契数,区间和为多少.开始sum1为区间长度,之后在单点做了修改以后对其更新,需要的时候用其覆盖sum. 1 #include<cstdio> 2 #include<cstring>

hdu 4893 Wow! Such Sequence!(线段树)

题目链接:hdu 4983 Wow! Such Sequence! 题目大意:就是三种操作 1 k d, 修改k的为值增加d 2 l r, 查询l到r的区间和 3 l r, 间l到r区间上的所以数变成最近的斐波那契数,相等的话取向下取. 解题思路:线段树,对于每个节点新增一个bool表示该节点以下的位置是否都是斐波那契数. #include <cstdio> #include <cstring> #include <cstdlib> #include <algor

HDU 4893 Wow! Such Sequence 线段树暴力

题意:n个数 初始为0,三个操作:给某个数加上d,查询区间和,把区间[l,r]中每个a[i]变为离a[i]最近的斐波那契数,n,m<=1e5. 无操作1情况下,每个点最多变化一次,每次修改logn,算上操作1 最坏情况下修改n+m次 O((n+m)logn). 对区间设个标记 线段树暴力即可. #include <bits/stdc++.h> using namespace std; typedef long long ll; const ll mod=1e9+7; const int

蓝桥杯Log大侠(线段树单点区间更新)

标题:Log大侠 atm参加了速算训练班,经过刻苦修炼,对以2为底的对数算得飞快,人称Log大侠. 一天,Log大侠的好友 drd 有一些整数序列需要变换,Log大侠正好施展法力... 变换的规则是: 对其某个子序列的每个整数变为: [log_2 (x) + 1]  其中 [] 表示向下取整,就是对每个数字求以2为底的对数,然后取下整.     例如对序列 3 4 2 操作一次后,这个序列会变成 2 3 2.         drd需要知道,每次这样操作后,序列的和是多少. [输入格式] 第一行

hdu 4893 (多校1007)Wow! Such Sequence!(线段树&amp;二分&amp;思维)

Wow! Such Sequence! Time Limit: 10000/5000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 352    Accepted Submission(s): 104 Problem Description Recently, Doge got a funny birthday present from his new friend, Prot

HDOJ 4893 Wow! Such Sequence!

题意是这样的,给定一个n个元素的数组,初始值为0,3种操作: 1 k d将第k个数增加d: 2 l r 询问区间l...r范围内数之和: 3 l r 表示将区间l...r内的数变成离他最近的斐波那契数,要求尽量小. 线段树操作题目,其中对于第三种操作用一个懒惰标记一下,表示l...r内的数是不是已经变成斐波那契数,如果是的话,求和就是其相应数的斐波那契数之和. 代码: 1 //Template updates date: 20140718 2 #include <bits/stdc++.h>

HDU4893 Wow! Such Sequence! 线段树

题意:给你一个序列,其中有三种操作 1)位置为K 的数+ D 2)求 l-r 区间和 3)把 l-r 区间里面的所有数都变为理它最近的斐波纳契数 解题思路:这个题的区间更新其实可以在单点更新的时候就得出,为节点维护两个 和,一个是 斐波纳契和 一个是正常和 ,再看这个区间有没有被3覆盖,特判一下就行了. 解题代码: 1 // File Name: 1007.cpp 2 // Author: darkdream 3 // Created Time: 2014年07月29日 星期二 12时49分33

2014多校3 Wow! Such Sequence!线段树

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4893 这题实在是让人纠结啊--好久不写线段树的题了,因为这几天学伸展树,然后觉得线段树小case了.没想到栽在这题上了.尼玛-- 自己把自己给搞晕了--想复杂了,都不懂得预处理一下,唉--还得怒刷几十道啊!! #include <iostream> #include <cstdio> #include <cstring> #include <cmath> #in

HDU4893:Wow! Such Sequence!(线段树lazy)

Problem Description Recently, Doge got a funny birthday present from his new friend, Protein Tiger from St. Beeze College. No, not cactuses. It's a mysterious blackbox. After some research, Doge found that the box is maintaining a sequence an of n nu

HDU 4902 线段树(区间更新)

Nice boat Time Limit: 30000/15000 MS (Java/Others)    Memory Limit: 131072/131072 K (Java/Others)Total Submission(s): 353    Accepted Submission(s): 169 Problem Description There is an old country and the king fell in love with a devil. The devil alw