线段树单点更新区间最大值 hdoj1754I Hate It

题目:hdoj1754 I  Hate It

分析:更新的话,建树的时候保存叶子编号的的节点信息,然后从下往上更新就ok。

求和的话,从根节点开始,然后找在根的左边还是右边,然后递归找一个所有中的最大值即可、

代码:

#include <cstdio>
#include <algorithm>
#include <iostream>
using namespace std;
const int N = 205000;
struct Node
{
    int l,r;
    int sum;
};
Node tree[4*N];
int a[N];
int fa[N];
void build(int l,int r,int v)
{
    tree[v].l=l;
    tree[v].r=r;
    if(l==r)
    {
        fa[l]=v;
        tree[v].sum=a[l];
        return ;
    }
    int mid=(l+r)>>1;
    build(l,mid,v*2);
    build(mid+1,r,v*2+1);
    tree[v].sum=max(tree[v+v].sum,tree[v+v+1].sum);
}

void update(int t,int p,int x)
{
    if(tree[t].sum<p)
        tree[t].sum=p;
    if(t==1)
        return ;
    update(t/2,p,x);
}
int queue(int a,int b,int v)
{
    if(tree[v].l==a&&tree[v].r==b)
    {
        return tree[v].sum;
    }
    int mid=(tree[v].l+tree[v].r)>>1;
    if(b<=mid) return queue(a,b,v+v);
    else if(a>mid) return queue(a,b,v+v+1);
    else return max(queue(a,mid,v*2),queue(mid+1,b,v*2+1));
}
int main()
{
    //freopen("a.txt","r",stdin);
    int n,m;
    while(~scanf("%d%d",&n,&m))
    {
        for(int i=1;i<=n;i++)
            scanf("%d",&a[i]);
        build(1,n,1);
        while(m--)
        {
            char c;
            int x,y;
            scanf("%*c%c",&c);
            scanf("%d%d",&x,&y);
            if(c=='Q')
                printf("%d\n",queue(x,y,1));
            else if(c=='U')
                update(fa[x],y,x);
        }
    }
    return 0;
}
时间: 2024-08-15 07:54:05

线段树单点更新区间最大值 hdoj1754I Hate It的相关文章

HDU 1754 I Hate It 线段树 单点更新 区间最大值

1 #include<iostream> 2 #include<string> 3 #include<algorithm> 4 #include<cstdlib> 5 #include<cstdio> 6 #include<set> 7 #include<map> 8 #include<vector> 9 #include<cstring> 10 #include<stack> 11 #

【HDU】1754 I hate it ——线段树 单点更新 区间最值

I Hate It Time Limit: 9000/3000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 37448    Accepted Submission(s): 14816 Problem Description 很多学校流行一种比较的习惯.老师们很喜欢询问,从某某到某某当中,分数最高的是多少.这让很多学生很反感. 不管你喜不喜欢,现在需要你做的是,就是按照老师的要

HDU 1754 I Hate It 线段树单点更新求最大值

题目链接 线段树入门题,线段树单点更新求最大值问题. #include <iostream> #include <cstdio> #include <cmath> #include <cstring> #include <algorithm> #define N 200005 using namespace std; int data[N]; struct Tree { int l,r,ans; }tree[N*4]; void build(in

hdu 3308 线段树单点更新 区间合并

http://acm.hdu.edu.cn/showproblem.php?pid=3308 学到两点: 1.以区间端点为开始/结束的最长......似乎在Dp也常用这种思想 2.分类的时候,明确标准逐层分类,思维格式: 条件一成立: { 条件二成立: { } else { } } else { 条件二成立: { } else { } } 上面的这种方式很清晰,如果直接想到那种情况iif(条件一 &条件二)就写,很容易出错而且把自己搞乱,或者情况不全,,,我就因为这WA了几次 3.WA了之后 ,

hdu2795(线段树单点更新&amp;区间最值)

题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=2795 题意:有一个 h * w 的板子,要在上面贴 n 条 1 * x 的广告,在贴第 i 条广告时要尽量将其靠上贴,并输出其最上能贴在哪个位置: 思路:可以将每行剩余空间大小存储到一个数组中,那么对于当前 1 * x 的广告,只需找到所有剩余空间大于的 x 的行中位置最小的即可: 不过本题数据量为 2e5,直接暴力因该会 tle.可以用个线段树维护一下区间最大值,然后查询时对线段树二分即可: 代码

hdu - 4973 - A simple simulation problem.(线段树单点更新 + 区间更新)

题意:初始序列 1, 2, ..., n,m次操作(1 <= n,m<= 50000),每次操作可为: D l r,将区间[l, r]中的所有数复制一次: Q l r,输出区间[l, r]中同一数字个数的最大值. (0 <= r – l <= 10^8, 1 <= l, r <= 序列元素个数) 题目链接:http://acm.hdu.edu.cn/showproblem.php?pid=4973 -->>因为区间内数字是依次递增的,所以可以以数字为叶建线段

HDU 2795 Billboard (线段树 单点更新 区间求最大值)

题目连接:http://acm.hdu.edu.cn/showproblem.php?pid=2795 题意:有一块h*w 的广告版,有n块1*w[i]的广告,就着放广告尽量在顶上,尽量先放左边的原则,问在第几行能把广告放下,如果放不下,就打印-1: 思路:我们可以根据每一行建树,每一个子叶表示每一行的容量,而节点存放子节点的最大值,然后从最顶到底,快速查找能存放下广告的一行. 总之还是简单的线段树问题,难点在于抽象模型. #include <iostream> #include <cs

POJ 2892 Tunnel Warfare(线段树单点更新区间合并)

Tunnel Warfare Time Limit: 1000MS   Memory Limit: 131072K Total Submissions: 7876   Accepted: 3259 Description During the War of Resistance Against Japan, tunnel warfare was carried out extensively in the vast areas of north China Plain. Generally sp

HDU 3308 LCIS (线段树&#183;单点更新&#183;区间合并)

题意  给你一个数组  有更新值和查询两种操作  对于每次查询  输出对应区间的最长连续递增子序列的长度 基础的线段树区间合并  线段树维护三个值  对应区间的LCIS长度(lcis)  对应区间以左端点为起点的LCIS长度(lle)  对应区间以右端点为终点的LCIS长度(lri)  然后用val存储数组对应位置的值  当val[mid + 1] > val[mid] 的时候就要进行区间合并操作了 #include <cstdio> #include <algorithm>