HDU - 4027 Can you answer these queries?(线段树)

 

 

给定一个长度为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:\n", ++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\n", query(1, l, r));
                                else change(1, l, r);
                }
                printf("\n");
        }
}

 

posted @ 2018-08-11 10:08  jvruodejrLS  阅读(124)  评论(0编辑  收藏  举报

Contact with me