【线段树】hdu 1754 I Hate It

【线段树】hdu 1754 I Hate It

题目链接:hdu 1754 I Hate It

题目大意

N个学生的初始成绩已知,操作m次,每次要么将第i个学生的成绩更新,要么查找区间【x,y】的最大成绩。

很显然这是一道线段树,点修改、区间查询,笔者第三道线段树,完全自己敲的,直接AC~(≧▽≦)/~啦啦啦。

如果单纯查找区间最大值,时间复杂度O(N),而线段树O(logN),当查询的次数非常多时,显然后者更高效!

说一下思路

  • 线段树的点修改【点更新】:直接将叶节点更新为输入的数据,对照“敌兵布阵”那道题增加或减少,略作修改即可
  • 线段树的区间查询【区间最大值】:在建树、update过程中注意维护每个节点的num,它的值取决于左孩子线段最小值和右孩子线段最小值的更小者,query()时讨论区间所属范围直接递归即可

参考代码

/*Author:Hacker_vision*/
#include<bits/stdc++.h>
using namespace  std;

const int _max = 2e5 + 10;
int n,m,a[_max],x,y;
char s[100];
struct segTree{
  int lc,rc;
  int num;
}segTree[_max<<2];

void build(int root,int L,int R){//建立线段树O(logN)
  segTree[root].lc=L;
  segTree[root].rc=R;
  if(L==R) {
    segTree[root].num = a[L];
    return;
  }
  int mid = (L + R) >> 1;
  build(root<<1,L,mid);//构建左子树
  build(root<<1|1,mid+1,R);//构建右子树
  segTree[root].num=max(segTree[root<<1].num,segTree[root<<1|1].num);//更新父节点
}

void update(int root,int pos,int data){//点修改O(logN)
  if(segTree[root].lc==pos&&segTree[root].rc==pos){
    segTree[root].num = data; //直接更新
    return;
  }
  int mid = (segTree[root].lc + segTree[root].rc) >> 1;
  if(pos <= mid) update(root<<1,pos,data);
  else update(root<<1|1,pos,data);
  segTree[root].num=max(segTree[root<<1].num,segTree[root<<1|1].num);//回溯更新父节点
}

int query(int root,int L,int R){//区间查询(查询最小值)
  if(segTree[root].lc == L&&segTree[root].rc==R) return segTree[root].num;
  int mid = (segTree[root].lc + segTree[root].rc) >> 1;
  if(R <= mid) return query(root<<1,L,R);
  else if(mid < L) return query(root<<1|1,L,R);
  else return max(query(root<<1,L,mid),query(root<<1|1,mid+1,R));
}

int main(){
 // freopen("input.txt","r",stdin);
  while(scanf("%d%d",&n,&m)==2){
    for(int i = 1; i <= n; ++ i)
        scanf("%d",a+i);
    build(1,1,n);
    for(int i = 0; i < m; ++ i){
        scanf("%s%d%d",s,&x,&y);
        if(s[0]==‘U‘) update(1,x,y);
        else printf("%d\n",query(1,x,y));
    }
  }
  return 0;
}

  • 加粗 Ctrl + B
  • 斜体 Ctrl + I
  • 引用 Ctrl + Q
  • 插入链接 Ctrl + L
  • 插入代码 Ctrl + K
  • 插入图片 Ctrl + G
  • 提升标题 Ctrl + H
  • 有序列表 Ctrl + O
  • 无序列表 Ctrl + U
  • 横线 Ctrl + R
  • 撤销 Ctrl + Z
  • 重做 Ctrl + Y

版权声明:本文为博主原创文章,未经博主允许不得转载。

时间: 2024-08-11 17:27:50

【线段树】hdu 1754 I Hate It的相关文章

线段树 [HDU 3308] LCIS

LCIS Time Limit: 6000/2000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 4437    Accepted Submission(s): 2006 Problem Description Given n integers.You have two operations:U A B: replace the Ath number by B. (index

线段树 [HDU 1166]

敌兵布阵 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total Submission(s): 46775    Accepted Submission(s): 19828 Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任务就

[后缀数组+dp/AC自动机+dp+线段树] hdu 4117 GRE Words

题意: 给你N个字符串, N(1 <= N <= 2w), 所有串的长度加一起不超过30w.每个串有个值.这个值[-1000, 1000]. 问不打乱字符串顺序,从中取若干个字符串,使得前一个串是后一个串的子串,求满足前面调条件的字符串值得和最大,求这个值. 思路: 其实就是一个很明显的dp. dp[i]代表以第i个字符串结尾的最大权值. 但是就是子串这个问题怎么处理. 由于这题数据比较水可以用后缀数组处理这个问题. 将所有字符串拼接,做sa. 每次在height数组里往上和往下寻找公共前缀等

【模板】吉司机线段树 HDU 5306 Gorgeous Sequence

也叫小清新线段树,用于解决区间最值修改问题 具体可以参考jiry_2神犇的集训队论文和WC2016上的PPT 此题就作为模板好了,模板的话写法是比较精妙的 #include<bits/stdc++.h> using namespace std; #define go(i,a,b) for(int i=a;i<=b;++i) #define com(i,a,b) for(int i=a;i>=b;--i) #define mem(a,b) memset(a,b,sizeof(a))

#树套树,二维线段树#HDU 4819 Mosaic

题目 多组数据,给定一个\(n*n\)的矩阵(\(n\leq 80,a_{i,j}\leq 10^9\)) 多组询问一个以\((x,y)\)为中心,边长为\(L\)的子矩阵最大值\(mx\)和最小值\(mn\), 并将\((x,y)\)这一个位置修改为\(\lfloor\frac{mn+mx}{2}\rfloor\),每次询问输出修改后的\((x,y)\) 分析 二维线段树裸题,反正之前也没敲过, 其实和一维线段树相近,找到\(lx\sim rx\)的下标 再按照一维线段树的方式修改最大最小值就

线段树 HDU 3397(真)

5 种操作  0 1 然后 异或 似乎这种2个更新的先后每次都搞不清 覆盖有覆盖就可以不异或 也不知道为什么 #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define MAXN 100010 struct node { int l,r,ls,rs,ms; // 左边连续的1 右边 最多 int lz,rz,mz; // 0 int XOR,cov; // 异

线段树 HDU 3308

t 题目大意:给你n个数,m个操作.操作有两种:1.U x y 将数组第x位变为y   2. Q x y 问数组第x位到第y位连续最长子序列的长度.对于每次询问,输出一个答案 #include<stdio.h> #include<string.h> #include<algorithm> using namespace std; #define MAXN 100010 struct node { int l,r,ls,rs,ms;//维护从左边开始 最大 到右边结束 3

bzoj 3038: 上帝造题的七分钟2 线段树||hdu 4027

3038: 上帝造题的七分钟2 Time Limit: 3 Sec  Memory Limit: 128 MBSubmit: 1066  Solved: 476[Submit][Status][Discuss] Description XLk觉得<上帝造题的七分钟>不太过瘾,于是有了第二部."第一分钟,X说,要有数列,于是便给定了一个正整数数列.第二分钟,L说,要能修改,于是便有了对一段数中每个数都开平方(下取整)的操作.第三分钟,k说,要能查询,于是便有了求一段数的和的操作.第四分

线段树 [HDU 1199] Color the Ball

Color the Ball Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 4529    Accepted Submission(s): 1114 Problem Description There are infinite balls in a line (numbered 1 2 3 ....), and initially a

线段树 hdu 4027

***又是超时的问题,当一个区间全是1时,再去开方和不开方是一样的,所以在这一步不需要再往底层递归了*** #include <iostream> #include <cstdio> #include <cstring> #include <algorithm> #include <stack> #include <queue> #include <cmath> using namespace std; typedef l