• HDU 4027 Can you answer these queries?(线段树区间开方)


    Can you answer these queries?

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)
    Total Submission(s): 16260    Accepted Submission(s): 3809

    Problem Description
    A lot of battleships of evil are arranged in a line before the battle. Our commander decides to use our secret weapon to eliminate the battleships. Each of the battleships can be marked a value of endurance. For every attack of our secret weapon, it could decrease the endurance of a consecutive part of battleships by make their endurance to the square root of it original value of endurance. During the series of attack of our secret weapon, the commander wants to evaluate the effect of the weapon, so he asks you for help.
    You are asked to answer the queries that the sum of the endurance of a consecutive part of the battleship line.

    Notice that the square root operation should be rounded down to integer.
     
    Input
    The input contains several test cases, terminated by EOF.
      For each test case, the first line contains a single integer N, denoting there are N battleships of evil in a line. (1 <= N <= 100000)
      The second line contains N integers Ei, indicating the endurance value of each battleship from the beginning of the line to the end. You can assume that the sum of all endurance value is less than 263.
      The next line contains an integer M, denoting the number of actions and queries. (1 <= M <= 100000)
      For the following M lines, each line contains three integers T, X and Y. The T=0 denoting the action of the secret weapon, which will decrease the endurance value of the battleships between the X-th and Y-th battleship, inclusive. The T=1 denoting the query of the commander which ask for the sum of the endurance value of the battleship between X-th and Y-th, inclusive.
     
    Output
    For each test case, print the case number at the first line. Then print one line for each query. And remember follow a blank line after each test case.
     
    Sample Input
    10
    1 2 3 4 5 6 7 8 9 10
    5
    0 1 10
    1 1 10
    1 1 5
    0 5 8
    1 4 8
     
    Sample Output
    Case #1:
    19
    7
    6
     
     
    题目链接:HDU 4027
    一开始用分块做的,可惜无限超时,这题如果用分块写,更新用lazy标记可以做到$sqrt(N)$,但是求和的复杂度不是$sqrt(N)$,因为区间开方之和不等于和的开方。只能用线段树了,显然一个数被向下取整开方太多次只能为0或者1,因此记录一下一个区间被开方的次数即可,小于$2^{63}$的非负数数开7次一定为0或者1,因此如果一个区间被开方次数大于等于7次就不用再继续往下更新了,当然前提是每一次都更新到叶子节点,因为区间只是记录了开方次数,sum得更新到叶子才算更新
    代码:
    #include <stdio.h>
    #include <iostream>
    #include <algorithm>
    #include <cstdlib>
    #include <sstream>
    #include <numeric>
    #include <cstring>
    #include <bitset>
    #include <string>
    #include <deque>
    #include <stack>
    #include <cmath>
    #include <queue>
    #include <set>
    #include <map>
    using namespace std;
    #define INF 0x3f3f3f3f
    #define LC(x) (x<<1)
    #define RC(x) ((x<<1)+1)
    #define MID(x,y) ((x+y)>>1)
    #define CLR(arr,val) memset(arr,val,sizeof(arr))
    #define FAST_IO ios::sync_with_stdio(false);cin.tie(0);
    typedef pair<int, int> pii;
    typedef long long LL;
    const double PI = acos(-1.0);
    const int N = 100010;
    struct seg
    {
        int l, mid, r;
        LL sum;
        int cnt;
    };
    seg T[N << 2];
    LL arr[N];
    
    void pushup(int k)
    {
        T[k].sum = T[LC(k)].sum + T[RC(k)].sum;
    }
    void build(int k, int l, int r)
    {
        T[k].l = l;
        T[k].r = r;
        T[k].mid = MID(l, r);
        T[k].sum = T[k].cnt = 0;
        if (l == r)
            T[k].sum = arr[l];
        else
        {
            build(LC(k), l, T[k].mid);
            build(RC(k), T[k].mid + 1, r);
            pushup(k);
        }
    }
    void SQ(int k, int l, int r)
    {
        if (l <= T[k].l && T[k].r <= r)
            ++T[k].cnt;
        if (T[k].cnt >= 7)
            return;
        if (T[k].l == T[k].r)
        {
            T[k].sum = sqrt(T[k].sum);
            return ;
        }
        if (r <= T[k].mid)
            SQ(LC(k), l, r);
        else if (l > T[k].mid)
            SQ(RC(k), l, r);
        else
            SQ(LC(k), l, T[k].mid), SQ(RC(k), T[k].mid + 1, r);
        pushup(k);
    }
    LL query(int k, int l, int r)
    {
        if (l <= T[k].l && T[k].r <= r)
            return T[k].sum;
        else
        {
            if (r <= T[k].mid)
                return query(LC(k), l, r);
            else if (l > T[k].mid)
                return query(RC(k), l, r);
            else
                return query(LC(k), l, T[k].mid) + query(RC(k), T[k].mid + 1, r);
        }
    }
    int main(void)
    {
        int i;
        int tcase = 1;
        int n, m;
        while (~scanf("%d", &n))
        {
            for (i = 1; i <= n; ++i)
                scanf("%I64d", &arr[i]);
            build(1, 1, n);
            scanf("%d", &m);
            printf("Case #%d:
    ", tcase++);
            while (m--)
            {
                int l, r, ops;
                scanf("%d%d%d", &ops, &l, &r);
                if (l > r)
                    swap(l, r);
                if (!ops)
                    SQ(1, l, r);
                else
                    printf("%I64d
    ", query(1, l, r));
            }
            puts("");
        }
        return 0;
    }
  • 相关阅读:
    cordova环境配置
    2016年读书计划
    红皇后假说
    微信OAuth2.0网页授权
    2016年碎语
    Apache + PHP 环境搭建
    各种环境配置
    技术名词记
    使用新浪云(SAE)实现基于mySql和微信公众平台的关键字请求响应服务
    为什么安装office后,xls文件不显示excel图标
  • 原文地址:https://www.cnblogs.com/Blackops/p/6978394.html
Copyright © 2020-2023  润新知