zoukankan      html  css  js  c++  java
  • HDU 1754 I hate it 树状数组维护区间最大值

    Problem Description

    很多学校流行一种比较的习惯。老师们很喜欢询问,从某某到某某当中,分数最高的是多少。
    这让很多学生很反感。

    不管你喜不喜欢,现在需要你做的是,就是按照老师的要求,写一个程序,模拟老师的询问。当然,老师有时候需要更新某位同学的成绩。

    Input

    本题目包含多组测试,请处理到文件结束。
    在每个测试的第一行,有两个正整数 N 和 M ( 0<N<=200000,0<M<5000 ),分别代表学生的数目和操作的数目。
    学生ID编号分别从1编到N。
    第二行包含N个整数,代表这N个学生的初始成绩,其中第i个数代表ID为i的学生的成绩。
    接下来有M行。每一行有一个字符 C (只取'Q'或'U') ,和两个正整数A,B。
    当C为'Q'的时候,表示这是一条询问操作,它询问ID从A到B(包括A,B)的学生当中,成绩最高的是多少。
    当C为'U'的时候,表示这是一条更新操作,要求把ID为A的学生的成绩更改为B。

    Output

    对于每一次询问操作,在一行里面输出最高成绩。

    Sample Input

    5 6
    1 2 3 4 5
    Q 1 5
    U 3 6
    Q 3 4
    Q 4 5
    U 2 9
    Q 1 5

    Sample Output

    5
    6
    5
    9

    分析

      今天突然想起我ST表还不会打,所以打算找一个区间最大值来做,于是就有了这道题,但我做的时候,突然好奇树状数组能不能来干这件事,想了想,魔改了一下代码,然后发现一直改不对,然后就去百度了一下,发现对于单点修改的问题,树状数组还是可以解决的,不必建立线段树。

      对于修改,如果把所有的点都重新计算一边,固然可以,但是效率太低,所以考虑树状数组的特有性质,对于一个点,只有距离在lowbit之内的点才能影响到它,比如点5,lowbit5=1,故只有自己影响自己,而4呢,lowbit4=4,所以影响它的点有1,2,3,而3=4-1,2=4-2,1还用不用考虑呢?显然是不用的,因为1是2的儿子,在修改2的时候便已经考虑过1了,所以只需一个循环套循环就能解决这个问题。

      对于查询,求区间加法的时候可以进行加减,但最大值显然不行,所以考虑别的查询方法。如果查询区间[l,r]的话,那么如果r-lowbit(r)>l,说明r的范围不包括l,所以可以将这个区间分成两部分[r-lowbit r+1,r]

    和区间[l,r-lowbit r],而前者就恰好是tree[r],可以自行取值验证,如果r-lowbit(r)<l呢,说明r的范围已经包括了l,那么就将这个区间分为两部分,a[r]和[l,r-1],然后再递归查询就行,你会发现递归是没有终点的,会死循环,所以要加一个终点,终点显然就是l==r,这样的话区间就只包括a[r]了,所以直接返回a[r]的值,这样就完成了树状数组的区间最大值查询,区间最小值也是一样的道理,换一下函数名就行了,是不是很神奇呢?

      于是就掌控了一门神奇的技能,于是我还是没练习ST表,算了晚上再弄吧

      

     1 #include<cstdio>
     2 #include<algorithm>
     3 #include<cstring>
     4 using namespace std;
     5 const int N=2e5+10;
     6 int lowbit(int x){
     7     return x&-x;
     8 }
     9 int tmx[N],a[N],n;
    10 void Add(int x){
    11     while(x<=n){
    12         tmx[x]=a[x];
    13         int lim=lowbit(x);
    14         for(int i=1;i<lim;i<<=1){
    15             tmx[x]=max(tmx[x],tmx[x-i]);
    16         }
    17         x+=lowbit(x);
    18     }
    19 }
    20 int query(int l,int r){
    21     if(l==r)return a[l];
    22     if(r-lowbit(r)>l)return max(tmx[r],query(l,r-lowbit(r)));
    23     else return max(a[r],query(l,r-1));
    24 }
    25 int main(){
    26     int m;
    27     while(~scanf("%d%d",&n,&m)){
    28         memset(tmx,0,sizeof(tmx));
    29         for(int i=1;i<=n;i++)
    30             scanf("%d",&a[i]),Add(i);
    31         while(m--){
    32             char op[5];int l,r;
    33             scanf("%s%d%d",op,&l,&r);
    34             if(op[0]=='Q')printf("%d
    ",query(l,r));
    35             else {
    36                 a[l]=r;
    37                 Add(l);
    38             }
    39         }
    40     }
    41     return 0;
    42 }
  • 相关阅读:
    RSA加密及加签
    间隔Ns请求某函数并且有timeout
    关于Erlang中的behaviour
    Erlang&RabbitMQ服务安装配置
    java IO流详解
    Uncaught TypeError: Cannot read property 'options' of undefined
    sql server 数据修改不了的设计
    Android多点触控详解
    java实现图的遍历(深度优先遍历和广度优先遍历)
    判断输入的8个数字不是符合8X8皇后棋盘
  • 原文地址:https://www.cnblogs.com/anyixing-fly/p/12462674.html
Copyright © 2011-2022 走看看