zoukankan      html  css  js  c++  java
  • HDU

    给定一个长度为n的序列,m次操作。

    每次操作

      可以将一个区间内的所有数字变为它的根号。

      可以查询一个区间内所有元素的和。

    线段树的初级应用。

    如果把一个区间内的元素都改为它的根号的话,是需要每个数字都进行修改的。这样就会超时。

    一个优化就是区间修改的当区间时,若区间长度等于区间和,那这个区间里的所有元素都不用修改了。

    而题目中区间里的元素之和最大是 2^63,时间完全够用。

    #include <iostream>
    #include <cstdlib>
    #include <cstdio>
    #include <cmath>
    using namespace std;
    #define maxn 100000 + 1000
    #define LL long long
    #define in_int(x) int x; scanf("%d", &x);
    
    struct Sect
    {
            int l, r, flag;
            LL sum;
            Sect() : flag(0) {}
    }
    t[4*maxn];
    
    LL
            n, a[4*maxn];
    
    void build(int id, int l, int r)
    {
            if (l == r)
            {
                    t[id].sum = a[l];
                    t[id].l = l, t[id].r = r;
                    return;
            }
            int mid = (l+r) >> 1;
            build(id*2, l, mid);
            build(id*2+1, mid+1, r);
            t[id].sum = t[id*2].sum + t[id*2+1].sum;
            t[id].l = t[id*2].l, t[id].r = t[id*2+1].r;
    }
    
    //void update(int id, int x, int val)
    //{
    //        if(t[id].l == t[id].r)
    //        {
    //                if (t[id].l == x) t[id].sum += val;
    //                return;
    //        }
    //        int mid = (t[id].l+t[id].r) >> 1;
    //        if (x <= mid) update(id*2, x, val);
    //                else update(id*2+1, x, val);
    //        t[id].sum = t[id*2].sum + t[id*2+1].sum;
    //}
    
    //void markdown(int id)
    //{
    //        t[id].flag = 0;
    //        t[id].sum = (int)sqrt(t[id].sum);
    //        if (t[id*2].flag) markdown(id*2);
    //        t[id*2].flag = 1;
    //        if (t[id*2+1].flag) markdown(id*2+1);
    //        t[id*2+1].flag = 1;
    //}
    
    LL query(int id, int l, int r)
    {
            //if(t[id].flag) markdown(id);
            if (t[id].l >= l && t[id].r <= r) return t[id].sum;
            int mid = (t[id].l + t[id].r) >> 1;
            if (r <= mid) return query(id*2, l, r);
                    else if (l > mid) return query(id*2+1, l, r);
                    else return query(id*2, l, mid) + query(id*2+1, mid+1, r);
    }
    
    void change(int id, int l, int r)
    {
            if (t[id].l == t[id].r)
            {
                    t[id].sum = sqrt(t[id].sum);
                    return;
            }
    
            if (t[id].r - t[id].l + 1 == t[id].sum) return;
    
            int mid = (t[id].l + t[id].r) >> 1;
            if (r <= mid) change(id*2, l, r);
                    else if (l > mid) change(id*2+1, l, r);
                    else
                    {
                            change(id*2, l, mid);
                            change(id*2+1, mid+1, r);
                    }
    
            t[id].sum = t[id*2].sum + t[id*2+1].sum;
    }
    
    int main()
    {
            int n, ca = 0;
            while(scanf("%lld", &n) != EOF)
            {
                    for (int i = 1; i <= n; i++)
                            scanf("%lld", &a[i]);
    
                    build(1, 1, n);
    
                    printf("Case #%d:
    ", ++ca);
                    in_int(m);
    
                    for (int i = 1; i <= m; i++)
                    {
                            in_int(x);
                            in_int(l);
                            in_int(r);
    
                            if (l > r) swap(l, r);
                            if (x) printf("%lld
    ", query(1, l, r));
                                    else change(1, l, r);
                    }
                    printf("
    ");
            }
    }
  • 相关阅读:
    关于sql json数据的处理
    时间函数strtotime的强大
    /usr/bin/install: cannot create regular file `/usr/local/jpeg6/include/jconfig.h'
    linux安装php7.2.7
    关于sql时间方面的处理
    关于centos防火墙的一些问题
    linux 安装ssl 失败原因
    linux安装php7.2.7
    拾取坐标和反查询接口api
    【转】通过点击获取地址等信息、可以传值
  • 原文地址:https://www.cnblogs.com/ruthank/p/9458659.html
Copyright © 2011-2022 走看看