树状数组求最大值 (RMQ with Shifts)

代码:

#include <iostream>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
using namespace std;
const int Max=200010;
int RMQ[Max+10];
int total[Max];
int sum[35];
int N,M,cnt;
char ctr[35];

int bit(int x)
{//每一个下标管辖的范围
    return x&(-x);
}
int query(int first,int second)
{//查询
    int res=total[second];
    while(first<=second)
    {
        int key=bit(second);
        if(second-key>=first)
        {
            if(res>RMQ[second])
                res=RMQ[second];
            second=second-key;
        }
        else
        {
            if(res>total[second])
               res=total[second];
             second--;
        }
    }
    return res;
}
int updata(int x)
{//更新x位置节点
    for(int i=x;i<=N;i+=bit(i))
    {
        RMQ[i]=total[i];//利用原数组来更新树状数组
        for(int j=1;j<bit(i);j<<=1)
        {//这个是重点又一次扫描i节点所管辖的区间
              RMQ[i]=min(RMQ[i],RMQ[i-j]);
        }
    }
}
void solve()
{
    int len=strlen(ctr);
    cnt=0;
    memset(sum,0,sizeof(sum));
    for(int i=6; i<len; i++)
    {
        if(ctr[i]==')')
            break;
        if(ctr[i]==',')
        {
            cnt++;
            continue;
        }
        int t=ctr[i]-'0';
        sum[cnt]=t+sum[cnt]*10;
    }
    if(ctr[0]=='q')
        printf("%d\n",query(sum[0],sum[1]));
    else
    {
        int key=total[sum[0]];
        for(int i=cnt; i>=0; i--)
        {
            int q=total[sum[i]];
            total[sum[i]]=key;//先更新原数组
            updata(sum[i]);
            key=q;
        }
    }
}

int main()
{
    scanf("%d%d",&N,&M);
    for(int i=1;i<=N;i++)
    {
         scanf("%d",&total[i]);
         updata(i);
    }
    for(int i=0;i<M;i++)
    {
        scanf("%s",ctr);
        solve();
    }
    return 0;
}
时间: 2024-11-07 06:52:21

树状数组求最大值 (RMQ with Shifts)的相关文章

hdu 1754 树状数组求最大值

#include <stdio.h> #include <string> #define MAX(a,b) (a>b?a:b) #define Lowbit(x) (x & (-x)) int idx[200010], num[200010]; /*int Lowbit(int x) { return x&(-x); }*/ /*int MAX(int x, int y) { return x > y ? x:y; }*/ /* 对于区间 [l,r] 把

树状数组求逆序对

给定n个数,要求这些数构成的逆序对的个数.除了用归并排序来求逆序对个数,还可以使用树状数组来求解.树状数组求解的思路:开一个能大小为这些数的最大值的树状数组,并全部置0.从头到尾读入这些数,每读入一个数就更新树状数组,查看它前面比它小的已出现过的有多少个数sum,然后用当前位置减去该sum,就可以得到当前数导致的逆序对数了.把所有的加起来就是总的逆序对数.题目中的数都是独一无二的,这些数最大值不超过999999999,但n最大只是500000.如果采用上面的思想,必然会导致空间的巨大浪费,而且由

树状数组求区间最值

树状数组求区间最值 树状数组(Binary Index Tree)利用二进制的一些性质巧妙的划分区间,是一种编程,时间和空间上都十分理想的求区间和的算法,同样我们可以利用树状数组优美的区间划分方法来求一个序列的最值 约定以 num[]  表示原数组, 以 idx[] 表示索引数组, Lowbit(x)=x&(-x) 树状数组求和时通过构造数组 idx[] 使 idx[k]=sum(num[tk]), tk [k-Lowbit(k)+1,k], 使用同样的方法构造最值索引数组: 以最大值为例, 先

ZOJ-2386 Ultra-QuickSort 【树状数组求逆序数+离散化】

Description In this problem, you have to analyze a particular sorting algorithm. The algorithm processes a sequence of n distinct integers by swapping two adjacent sequence elements until the sequence is sorted in ascending order. For the input seque

POJ2985 The k-th Largest Group[树状数组求第k大值 并查集]

The k-th Largest Group Time Limit: 2000MS   Memory Limit: 131072K Total Submissions: 8807   Accepted: 2875 Description Newman likes playing with cats. He possesses lots of cats in his home. Because the number of cats is really huge, Newman wants to g

HDU 5249 离线树状数组求第k大+离散化

KPI Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java/Others)Total Submission(s): 1160    Accepted Submission(s): 488 Problem Description 你工作以后, KPI 就是你的全部了. 我开发了一个服务,取得了很大的知名度.数十亿的请求被推到一个大管道后同时服务从管头拉取请求.让我们来定义每个请求都有一个重要值.我的

树状数组求逆序数

poj 2299 树状数组求逆序数题目链接:http://poj.org/problem?id=2299 1 #include <stdio.h> 2 #include <string.h> 3 #include <iostream> 4 #include <algorithm> 5 #include <vector> 6 #include <queue> 7 #include <stack> 8 #include <

HDU 1394 Minimum Inversion Number (树状数组求逆序数)

Minimum Inversion Number Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others) Total Submission(s): 13942    Accepted Submission(s): 8514 Problem Description The inversion number of a given number sequence a1, a2, ..., a

hdu5792 World is Exploding(多校第五场)树状数组求逆序对 离散化

题目地址:http://acm.hdu.edu.cn/showproblem.php?pid=5792 题目描述:给你n个值,每个值用A[i]表示,然后问你能否找到多少组(a,b,c,d)四个编号,四个编号互不相同,然后a < b, c < d,a代表的值小于b代表的值,c代表的值大于d代表的值. 解题思路:先考虑a和b这两个编号,遍历每一个编号作为b,然后找到b前面有多少个小于b的值,就是对于这一个编号b合理的编号a,对于每一组a和b,就可以考虑c和d,能够满足条件c和d的很显然就是除去a和