HDU 4027—— Can you answer these queries?——————【线段树区间开方,区间求和】

Can you answer these queries?

Time Limit:2000MS     Memory Limit:65768KB     64bit IO Format:%I64d & %I64u

Submit Status Practice HDU 4027

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 2 63
  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

解题思路:刚开始看到题目的时候感觉蛮简单的,就是类似区间增减的感觉。但是慢慢写着写着感觉没法写了。于是就看了看网上别人的思路,发现原来平方藏有玄机。2^64如果要开方的话,最多也就开7次,所以如果对区间标记是否有结点仍能开方,就能省下很多的更新时间,如果能开方,就找到叶子结点进行开方操作,同时更新路径上的sumv数组和num数组,而询问就是简单的区间求和了。

#include<stdio.h>
#include<string.h>
#include<math.h>
#include<algorithm>
using namespace std;
#define mid (L+R)/2
#define lson rt*2,L,mid
#define rson rt*2+1,mid+1,R
#define LL long long
const int maxn=101000;
LL sumv[maxn*4];
int num[maxn*4];
void PushUP(int rt){
    sumv[rt]=sumv[rt*2]+sumv[rt*2+1];
    num[rt]=num[rt*2]+num[rt*2+1];
}
void build(int rt,int L,int R){
    if(L==R){
        scanf("%lld",&sumv[rt]);
        if(sumv[rt]==0||sumv[rt]==1){
            num[rt]=0;
        }else{
            num[rt]=1;
        }
        return ;
    }
    build(lson);
    build(rson);
    PushUP(rt);
}
void _sqrt(int rt,int L,int R){
    if(L==R){
        sumv[rt]=(LL)sqrt(sumv[rt]);
        if(sumv[rt]==0||sumv[rt]==1){
            num[rt]=0;
        }else{
            num[rt]=1;
        }
        return ;
    }
    _sqrt(lson);
    _sqrt(rson);
    PushUP(rt);
}
void update(int rt,int L,int R,int l_ran,int r_ran){
    if(l_ran<=L&&R<=r_ran){
        if(num[rt]!=0){
            _sqrt(rt,L,R);
        }
        return ;
    }
    if(l_ran<=mid){
        update(lson,l_ran,r_ran);
    }
    if(r_ran>mid){
        update(rson,l_ran,r_ran);
    }
    PushUP(rt);
}
LL query(int rt,int L,int R,int l_ran,int r_ran){
    if(l_ran<=L&&R<=r_ran){
        return sumv[rt];
    }
    LL ret=0;
    if(l_ran<=mid){
        ret+=query(lson,l_ran,r_ran);
    }
    if(r_ran>mid){
        ret+=query(rson,l_ran,r_ran);
    }
    return ret;
}
int main(){
    int n,m,cnt=0;
    while(scanf("%d",&n)!=EOF){
        build(1,1,n);
        printf("Case #%d:\n",++cnt);
        scanf("%d",&m);
        for(int i=0;i<m;i++){
            int f,tml,tmr;
            scanf("%d%d%d",&f,&tml,&tmr);
            if(tml>tmr){
                int k=tml;
                tml=tmr;
                tmr=k;
            }
            if(!f){
                update(1,1,n,tml,tmr);
            }else{
                printf("%lld\n",query(1,1,n,tml,tmr));
            }
        }
        printf("\n");
    }
    return 0;
}

  

时间: 2024-10-09 23:51:31

HDU 4027—— Can you answer these queries?——————【线段树区间开方,区间求和】的相关文章

HDU 4027 Can you answer these queries? (线段树+区间点修改)

题意:给你 n 个数,m个询问(c,x,y) c==0 把x,y区间的值变为原来的平方根(向下取整) c==1 计算x,y区间的和. 利用1的开方永远为1剪枝.. #include<cstdio> #include<stdlib.h> #include<string.h> #include<string> //#include<map> #include<cmath> #include<iostream> #include

HDU 4027 Can you answer these queries?(线段树,区间更新,区间查询)

题目 线段树 简单题意: 区间(单点?)更新,区间求和 更新是区间内的数开根号并向下取整 这道题不用延迟操作 //注意: //1:查询时的区间端点可能前面的比后面的大: //2:优化:因为每次更新都是开平方,同一个数更新有限次数就一直是1了,所以可以这样优化 #include <stdio.h> #include<math.h> #define N 100010 #define LL __int64 #define lson l,m,rt<<1 #define rson

HDU 4027 Can you answer these queries? 线段树裸题

题意: 给定2个操作 0.把区间的每个数sqrt 2.求和 因为每个数的sqrt次数很少,所以直接更新到底,用个标记表示是否更新完全(即区间内的数字只有0,1就不用再更新了) #include<stdio.h> #include<iostream> #include<algorithm> #include<vector> #include<cmath> #include<queue> #include<set> #incl

hdu 4027 Can you answer these queries? 线段树区间开根号,区间求和

Can you answer these queries? Time Limit: 1 Sec  Memory Limit: 256 MB 题目连接 http://acm.hdu.edu.cn/showproblem.php?pid=5195 Description A lot of battleships of evil are arranged in a line before the battle. Our commander decides to use our secret weapo

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): 9216    Accepted Submission(s): 2106 Problem Description A lot of battleships of evil are arranged in a line before

HDU 4027 Can you answer these queries?(线段树 区间不等更新)

题意  输入n个数  然后有两种操作   输入0时将给定区间所有数都变为自己的开方   输入1输出给定区间所有数的和 虽然是区间更新  但每个点更新的不一样  因此只能对单点进行更新  其实一个点最多被更新7次  2^64开平方7次后就变为1了  如果某个区间的数都变为了1  那么对这个区间的开方就不用考虑了   另外要注意给你的区间可能是反的 #include <bits/stdc++.h> #define lc p<<1,s,mid #define rc p<<1|

HDU 4027 Can you answer these queries? 线段树,区间修改

Can you answer these queries? 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 end

HDU - 4027 Can you answer these queries? (线段树区间更新+思维)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4027 题意:给定两种操作,查询(求出区间内的和),更新(区间内每个值都开根号,取整数) 题目给出所有数字之和小于263,所以最大的数最多7次也就变成1.所以在更新的时候加个判断条件,提前结束. 然后这道题目还有个坑,L有可能比R大,需要交换一下,(╬▔皿▔) . 1 #include <cstdio> 2 #include <algorithm> 3 #include <cmat

HDU 4027 Can you answer these queries?(线段树的单点更新+区间查询)

题目链接 题意 : 给你N个数,进行M次操作,0操作是将区间内的每一个数变成自己的平方根(整数),1操作是求区间和. 思路 :单点更新,区间查询,就是要注意在更新的时候要优化,要不然会超时,因为所有的数开几次方之后都会变成1,所以到了1不用没完没了的更新. 1 //HDU 4027 2 #include <cstdio> 3 #include <cstring> 4 #include <cmath> 5 #include <iostream> 6 #defi

HDU4027 Can you answer these queries 线段树区间求和+剪枝

给了你n,然后n个数字在一个数组中,接下来m个询问,每个询问三个数字 t,x,y,若t==0,那么修改区间[x,y]的每一个值,变为原来每个位置上的数 开根号取整,若t==1,那么对区间[x,y]求和 由于n,m,很大,所以树状数组铁定超时,若直接用线段树来做区间修改,那么也是超时,这类题目没别的方法了,静心剪枝,发现题目给的数据范围为2^63,有没有发现,2^63开根号 绝对不需要开10次,就能到1,到1以后就不需要再开了,意思就是若有某个区间[x,y]每一个点的值都为1时,这一段区间事实上是