树状数组区间求和与区间最值

//树状数组区间求和
//修改的时间复杂度为O(logn)  查询的时间复杂度为O(logn)。
/*lowbit函数这个函数的功能就是求某一个数的二进制表示中最低的一位1。
举个例子,x = 6,它的二进制为110,那么lowbit(x)就返回2,
因为最后一位1表示2。 而树状数组的求和与下标的二进制有关,详情见图
add函数即修改区间和 
query函数即查询区间和(从1到k),
查询a~b的区间和只需query(a)-query(b)。*/
#include
using namespace std;
const int N = 100005;
int n;
int dp[N] = {0};
int lowbit(int k)
{
    return k&-k;
}
void add(int k,int num)
{
    while(k<=n)
    {
        dp[k] += num;
        k += lowbit(k);
    }
}
int query(int k)
{
    int res = 0;
    while(k>0)
    {
        res += dp[k];
        k -= lowbit(k);
    }
    return res;
}
int main()
{
    cin >> n;
    for(int i=1; i<=n; ++i)
    {
        int num;    cin >> num;
        add(i,num);
    }
    int q;      cin >> q;
    while(q--)
    {
        int a,b;        cin >> a >> b;
        cout << query(b) - query(a) << endl;
    }
    return 0;
 }

//树状数组求区间最大值
//初始化的时间复杂度为O(Nlog(n)),
//修改的时间复杂度为log(n)*log(n),
//查询的时间复杂度为O(logn)。
/*与区间求和相似,初始化时树状数组的每个节点保存的是所包含的区间的最大值,
当查询的时候,利用lowboit函数跳跃查询,使得时间复杂度减小至logn
当修改时,需要修改的是指定区间上的最大值, */
#include
#include
using namespace std;
const int N = 100005;
int a[N] = {0};
int dp[N] = {0};
int n;
int lowbit(int k)
{
    return k&&-k;
}
void init()     //初始化 
{
    int  y;
    memset(dp, 0, sizeof(dp));
    for(int i = 1; i <= n; i++)
    {
        scanf("%d", &y);
        a[i] = y;
        dp[i] = y;
        for(int j = 1; j 1)
            dp[i] = dp[i] > dp[i-j] ? dp[i] : dp[i-j];
    }
}
void maxn(int x, int y)     //修改,将第x个元素改为y 
{
    a[x] = y;
    for(int i = x; i <= n; i += lowbit(i))
    {
        dp[i] = y;
        for(int j = 1; j < lowbit(i); j <<= 1)
        {
            dp[i] = dp[i] > dp[i-j] ? dp[i] : dp[i-j];
        }
    }
}
void query(int l, int r)        //查询 
{
    int ans = 0;
    while(1)
    {
        ans = ans > a[r] ? ans : a[r];
        if(r == l) break;
        for(r -= 1; r-l >= lowbit(r); r -= lowbit(r))
            ans = ans > dp[r] ? ans : dp[r];
    }
    cout << ans;
}
int main()
{
    cin >> n;
    init();
    /*int a,b;  cin >> a >> b;
    maxn(a,b);*/
    int l,r;    cin >> l >> r;
    query(l,r);
    return 0;
}

你可能感兴趣的:(树状数组区间求和与区间最值)