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


    http://acm.hdu.edu.cn/showproblem.php?pid=4027

    Time Limit: 4000/2000 MS (Java/Others)    Memory Limit: 65768/65768 K (Java/Others)

    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 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
    题目大意:
    一共有n个数,m个操作,操作分两种:0 x y表示将区间[x,y]的数开方,1 x y表示查询区间[x,y]的和。

    解题思路:

    很明显的线段树

    很容易想到区间更新的lazy思想,但是这道题的更新并不是简单的加减乘除,而是开方。但是开方的话我们无法通过延迟更新来减少时间复杂度,也就是说lazy思想在这里并不是太试用。

    那么我们想一想算术平方根,sqrt(1)=1,且考虑到数据范围为2的63次方,也就是说这个数最多只能开7次平方,因为接下来如何再开方都是1了。

    所以我们就可以从这点入手,当更新时我们不延迟更新了,需要我们判断一下是否需要更新。

    如果在这个区间内SegTree[rt].sum = SegTree[rt].r-SegTree[rt].l+1(就是区间内有点都为1)很明显这个时候不用更新区间,那就直接return。

    如果这个区间可以更新,那就直接更新这个区间。所以每次更新都更新到叶子结点,维护区间和就行了。

     

    除此之外,这题也有不少的坑点:

    1:要区分好那些数据是long long,那些是int

    2:注意每个样例后都要输出一个空行

    3:注意输入x,y后要检查是否x<=y,如果x>y,要交换x和y(最坑的点,做过那么多的区间查询,这是我遇见的第一个还设置这种坑的,有意思么。。。)

    代码如下:

    旧代码(变量名称不喜欢用了)

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <iostream>
      4 #include <string>
      5 #include <math.h>
      6 #include <algorithm>
      7 #include <vector>
      8 #include <queue>
      9 #include <set>
     10 #include <map>
     11 #include <math.h>
     12 const int INF=0x3f3f3f3f;
     13 typedef long long LL;
     14 const int mod=1e9+7;
     15 //const double PI=acos(-1);
     16 const int maxn=1e5+10;
     17 using namespace std;
     18 //ios::sync_with_stdio(false);
     19 //    cin.tie(NULL);
     20 
     21 int n,m;
     22 struct node
     23 {
     24     int l;
     25     int r;
     26     LL sum;
     27 }SegTree[maxn<<2];
     28 
     29 void PushUp(int rt)
     30 {
     31     SegTree[rt].sum=SegTree[rt<<1].sum+SegTree[rt<<1|1].sum;
     32 }
     33 
     34 void Build(int l,int r,int rt)
     35 {
     36     SegTree[rt].l=l;
     37     SegTree[rt].r=r;
     38     if(l==r)
     39     {
     40         scanf("%lld",&SegTree[rt].sum);
     41         return;
     42     }
     43     int mid=(l+r)>>1;
     44     Build(l,mid,rt<<1);
     45     Build(mid+1,r,rt<<1|1);
     46     PushUp(rt);
     47 }
     48 
     49 void Update(int L,int R,int rt)
     50 {
     51     int l=SegTree[rt].l;
     52     int r=SegTree[rt].r;
     53     if(L<=l&&R>=r)
     54     {
     55         if(SegTree[rt].sum==SegTree[rt].r-SegTree[rt].l+1)//说明该区间全是1,没必要开方
     56             return ;    
     57     }
     58     if(l==r)//该区间不为1 
     59     {
     60         SegTree[rt].sum=(LL)sqrt(SegTree[rt].sum*1.0);
     61         return ;
     62     }
     63     int mid=(l+r)>>1;
     64     if(L<=mid)
     65         Update(L,R,rt<<1);
     66     if(R>mid)
     67         Update(L,R,rt<<1|1);
     68     PushUp(rt);
     69 }
     70 
     71 LL Query(int L,int R,int rt)
     72 {
     73     int l=SegTree[rt].l;
     74     int r=SegTree[rt].r;
     75     if(L<=l&&R>=r)
     76     {
     77         return SegTree[rt].sum;
     78     }
     79     LL SUM=0;
     80     int mid=(l+r)>>1;
     81     if(L<=mid)
     82         SUM+=Query(L,R,rt<<1);
     83     if(R>mid)
     84         SUM+=Query(L,R,rt<<1|1);
     85     return SUM;
     86 }
     87 
     88 int main()
     89 {
     90     //freopen("sample.txt","r",stdin);
     91     int num=1;
     92     while(~scanf("%d",&n))
     93     {
     94         printf("Case #%d:
    ",num++);
     95         Build(1,n,1);
     96         scanf("%d",&m);
     97         for(int i=1;i<=m;i++)
     98         {
     99             int f,x,y;
    100             scanf("%d %d %d",&f,&x,&y);
    101             if(x>y)//坑点 
    102                 swap(x,y);
    103             if(f==0)
    104             {
    105                 Update(x,y,1);
    106             }
    107             else if(f==1)
    108             {
    109                 printf("%lld
    ",Query(x,y,1));
    110             }
    111         }
    112         printf("
    ");//坑点 
    113     }
    114     return 0;
    115 }
    View Code

    新代码:

      1 #include <stdio.h>
      2 #include <string.h>
      3 #include <iostream>
      4 #include <string>
      5 #include <math.h>
      6 #include <algorithm>
      7 #include <vector>
      8 #include <stack>
      9 #include <queue>
     10 #include <set>
     11 #include <map>
     12 #include <sstream>
     13 const int INF=0x3f3f3f3f;
     14 typedef long long LL;
     15 const double eps =1e-8;
     16 const int mod=1e9+7;
     17 const int maxn=2e5+10;
     18 using namespace std;
     19 
     20 struct node
     21 {
     22     int l,r;
     23     LL val;
     24 }Tr[maxn<<2];
     25 
     26 void PU(int u)    //pushup 
     27 {
     28     Tr[u].val=Tr[u<<1].val+Tr[u<<1|1].val;
     29 }
     30 
     31 void Build(int l,int r,int u) //建树 
     32 {
     33     Tr[u].l=l; Tr[u].r=r;
     34     if(l==r)
     35     {
     36         scanf("%lld",&Tr[u].val);
     37         return ;
     38     }
     39     int mid=(l+r)>>1;
     40     Build(l,mid,u<<1);
     41     Build(mid+1,r,u<<1|1);
     42     PU(u);
     43 }
     44 
     45 void Update(int L,int R,int u) //区间更新
     46 {
     47     int l=Tr[u].l; int r=Tr[u].r;
     48     if(L<=l&&R>=r)
     49     {
     50         if(Tr[u].val==r-l+1) return ; //说明该区间全是1,没必要开方
     51     }
     52     if(l==r) //该区间不为1
     53     {
     54         Tr[u].val=(LL)sqrt(Tr[u].val*1.0);
     55         return ;
     56     }
     57     int mid=(l+r)>>1;
     58     if(L<=mid) Update(L,R,u<<1);
     59     if(R>mid) Update(L,R,u<<1|1);
     60     PU(u);
     61 }
     62 
     63 LL Query(int L,int R,int u)    //区间查询 
     64 {
     65     int l=Tr[u].l; int r=Tr[u].r;
     66     if(L<=l&&R>=r)
     67     {
     68         return Tr[u].val;
     69     }
     70     int mid=(l+r)>>1;
     71     LL sum=0;
     72     if(L<=mid) sum+=Query(L,R,u<<1);
     73     if(R>mid) sum+=Query(L,R,u<<1|1);
     74     return sum;
     75 }
     76 
     77 int main()
     78 {
     79     #ifdef DEBUG
     80     freopen("sample.txt","r",stdin);
     81     #endif
     82     
     83     int n,m,cnt=0;
     84     while(~scanf("%d",&n))
     85     {
     86         printf("Case #%d:
    ",++cnt);
     87         Build(1,n,1);
     88         scanf("%d",&m);
     89         for(int i=1;i<=m;i++)
     90         {
     91             int op,l,r;
     92             scanf("%d %d %d",&op,&l,&r);
     93             if(l>r) swap(l,r); //坑点 
     94             if(op==0) Update(l,r,1);
     95             else if(op==1) printf("%lld
    ",Query(l,r,1));
     96         }
     97         printf("
    "); //坑点 
     98     }
     99     
    100     return 0;
    101 }

    -

  • 相关阅读:
    就南通大学教务管理系统微信公众号的个人看法
    设计一款给爸爸妈妈用的手机
    .NET中DLL“没有可放置在工具箱的组件”—FreeTextBox
    如何查看.Net源代码vs版本号以及C#项目中各文件的含义
    .NET在后置代码中输入JS提示语句(背景不会变白)
    Docker技术学习
    学习linux基本命令
    性能相关英文单词学习
    常见Http状态码的含义
    学习siege实战
  • 原文地址:https://www.cnblogs.com/jiamian/p/11408944.html
Copyright © 2020-2023  润新知