zoukankan      html  css  js  c++  java
  • Rikka with Sequence---hdu5828(区间更新与查找 线段树)

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

    给你n个数,m个操作,操作k,l,r,

    k=1时 区间[l,r]每个数加x;

    k=2时,区间[l,r]每个数开平方;

    k=3时,求区间[l,r]的和。

    开方的操作执行的次数,并不多到所以最后会出现很多相同的数,我们可以把相同的数统一减去一个数即可,但是数据中如果存在2 3 2 3 2 3 2 3,有10w次+6,然后开方,这样的话,时间复杂度也是很高的;所以我们可以看到,只要两个数相差一,开方后还相差一,那么我们可以减去一个数完成;

    #include<iostream>
    #include<algorithm>
    #include<string.h>
    #include<stdio.h>
    #include<math.h>
    using namespace std;
    #define N 100005
    #define met(a, b) memset(a, b, sizeof(a))
    #define mod 1000000007
    typedef long long LL;
    #define Lson r<<1
    #define Rson r<<1|1
    
    struct Tree
    {
        int L, R;
        LL lazy, Min, Max, sum;
        int mid() { return (L+R)/2; }
        int len() { return (R-L+1); }
    }a[N<<2];
    
    void BuildTree(int r, int L, int R)
    {
        a[r].L = L; a[r].R = R; a[r].lazy = 0;
    
        if(a[r].L == a[r].R)
        {
            scanf("%I64d", &a[r].sum);
            a[r].Max = a[r].Min = a[r].sum;
            return ;
        }
    
        BuildTree(Lson, L, a[r].mid());
        BuildTree(Rson, a[r].mid()+1, R);
    
        a[r].sum = a[Lson].sum + a[Rson].sum;
        a[r].Max = max(a[Lson].Max, a[Rson].Max);
        a[r].Min = min(a[Lson].Min, a[Rson].Min);
    }
    
    void Down(int r)
    {
        a[Lson].lazy += a[r].lazy; a[Rson].lazy += a[r].lazy;
    
        a[Lson].sum += a[Lson].len()*a[r].lazy;
        a[Rson].sum += a[Rson].len()*a[r].lazy;
    
        a[Lson].Max += a[r].lazy; a[Rson].Max += a[r].lazy;
        a[Lson].Min += a[r].lazy; a[Rson].Min += a[r].lazy;
    
        a[r].lazy = 0;
    }
    
    void Up(int r)
    {
        a[r].sum = a[Lson].sum + a[Rson].sum;
    
        a[r].Max = max(a[Lson].Max, a[Rson].Max);
        a[r].Min = min(a[Lson].Min, a[Rson].Min);
    }
    
    void Update1(int r, int L, int R, LL num)
    {
        a[r].sum += (R-L+1) * num;
        if(a[r].L == L && a[r].R == R)
        {
            a[r].Max += num;
            a[r].Min += num;
            a[r].lazy += num;
            return ;
        }
    
        Down(r);///往下传递Lazy;
    
        if(R <= a[r].mid())
            Update1(Lson, L, R, num);
        else if(L > a[r].mid())
            Update1(Rson, L, R, num);
        else
        {
            Update1(Lson, L, a[r].mid(), num);
            Update1(Rson, a[r].mid()+1, R, num);
        }
    
        Up(r);///往上传递Lazy;
    }
    void Update2(int r, int L, int R)
    {
        if(a[r].L == L && a[r].R == R)
        {
            if(a[r].Min == a[r].Max)///当区间内所有的数都相等时,相当于区间内所有数都减去同一个数;
            {
                LL num = (LL)sqrt(a[r].Max) - a[r].Max;
                a[r].sum += a[r].len() * num;
                a[r].lazy += num;
                a[r].Max += num;
                a[r].Min += num;
    
                return;
            }
            else if(a[r].Min + 1 == a[r].Max)///当数之间相差<=1的时候并且开方之后还是相差1的话,那么他们可以通过加一个数得到;
            {
                LL num1 = (LL)sqrt(a[r].Max);
                LL num2 = (LL)sqrt(a[r].Min);
                if(num1 == num2+1)
                {
                    LL num = num1 - a[r].Max;
                    a[r].sum += a[r].len() * num;
                    a[r].lazy += num;
                    a[r].Max += num;
                    a[r].Min += num;
                    return;
                }
            }
        }
    
        Down(r);
    
        if(R <= a[r].mid())
            Update2(Lson, L, R);
        else if(L > a[r].mid())
            Update2(Rson, L, R);
        else
        {
            Update2(Lson, L, a[r].mid());
            Update2(Rson, a[r].mid()+1, R);
        }
    
        Up(r);
    }
    LL Query(int r, int L, int R)
    {
        if(L == a[r].L && R == a[r].R)
        {
            return a[r].sum;
        }
        Down(r);
        if(R <= a[r].mid())
            return Query(Lson, L, R);
        else if(L > a[r].mid())
            return Query(Rson, L, R);
        else
        {
            LL ans1 = Query(Lson, L, a[r].mid());
            LL ans2 = Query(Rson, a[r].mid()+1, R);
            return ans1 + ans2;
        }
    }
    
    int main()
    {
        int T;
        scanf("%d", &T);
        while(T--)
        {
            int n, m, op, L, R; LL num;
    
            scanf("%d %d", &n, &m);
    
            BuildTree(1, 1, n);
    
            while(m--)
            {
                scanf("%d", &op);
                if(op == 1)
                {
                    scanf("%d %d %I64d", &L, &R, &num);
                    Update1(1, L, R, num);
                }
                else if(op == 2)
                {
                    scanf("%d %d", &L, &R);
                    Update2(1, L, R);
                }
                else
                {
                    scanf("%d %d", &L, &R);
                    LL ans = Query(1, L, R);
                    printf("%I64d
    ", ans);
                }
            }
        }
        return 0;
    }
    View Code
  • 相关阅读:
    Lua Coroutine详解
    Lua IO库详解
    vue 组件基本使用
    js 发送异步请求
    小程序保存图片到相册
    js 学习四 对象应用 吃货游戏
    js 学习三 Array
    js 学习二 字符串常用方法
    js 学习一 猜数字游戏
    phpmyadmin导入大容量.sql文件
  • 原文地址:https://www.cnblogs.com/zhengguiping--9876/p/5776361.html
Copyright © 2011-2022 走看看