码迷,mamicode.com
首页 > 编程语言 > 详细

树状数组维护区间最值

时间:2017-05-25 23:27:26      阅读:285      评论:0      收藏:0      [点我收藏+]

标签:pts   print   imp   lips   pac   .com   main   com   nbsp   

在区间求和时,我们只需求出 [1, r][1,l?1],利用前缀和的可减性,得到区间 [l,r] 的和。

但区间最值不满足这个性质。

我们可以把区间 [l,r] 拆分成若干个子区间,再合并得到答案。

画图可知,max_i需要的 max 只有 max_{i-2^0}, max_{i-2^1}, max_{i-2^2} ... max_{i-lowbit(i)+1}。

修改

void change(int r) {
    c[r] = a[r];
    for(int i = 1; i < lowbit(r); i <<= 1)
        c[r] = max(c[r], c[r-i]);
}

查询

我们找 [l, r] 的最值就是子区间最值的 max,即递减 r,在这里可以有个优化,即当找到一个 max_i??,有 i?lowbit(i)l 时,更

新后,i = i - lowbit(i),然后继续递减。当 l>r 就跳出循环。

int getmax(int l, int r) {
    int ret = a[r];
    while(l <= r) {
        ret = max(ret, a[r]);
        for(--r; r - l >= lowbit(r); r -= lowbit(r))
            ret = max(ret, c[r]);
    }
    return ret;
}
 

需要指出的是,它只支持末端插入,不支持单点修改操作。

 

技术分享

技术分享

#include<iostream>
#include<stdio.h>
#include<memory.h>
using namespace std;
int A[200005];
int C[200005];
int lowbit(int x)
{
    return x&(-x);
}

void update(int x)
{
    C[x]=A[x];
    for(int i=1; i<lowbit(x); i<<=1)
        C[x]=max(C[x],C[x-i]);
}

int query(int l,int r)
{
    int ans=A[r];
    while(l<=r)
    {
        ans=max(ans,A[r]);
        for(--r; r-l>=lowbit(r); r-=lowbit(r))
            ans=max(ans,C[r]);
    }
    return ans;
}

int main()
{
    int m,d;
    scanf("%d%d",&m,&d);
    int cnt = 0,t=0;
    for(int i = 0; i<m; i++)
    {
        char op;
        int n;
        scanf(" %c%d",&op,&n);
        if(op==A)
        {
            int temp = (n+t)%d;
            A[++cnt]=temp;
            update(cnt);
        }
        else
        {
            printf("%d\n",t = query(cnt-n+1,cnt));
        }
    }
    return 0;
}

 

树状数组维护区间最值

标签:pts   print   imp   lips   pac   .com   main   com   nbsp   

原文地址:http://www.cnblogs.com/wangkaipeng/p/6906215.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!