树状数组维护区间最值

题目描述
给你一个1->n的排列和一个栈,入栈顺序给定
你要在不打乱入栈顺序的情况下,对数组进行从大到小排序
当无法完全排序时,请输出字典序最大的出栈序列
输入描述:
第一行一个数n
第二行n个数,表示入栈的顺序,用空格隔开,结尾无空格
输出描述:
输出一行n个数表示答案,用空格隔开,结尾无空格
示例1
输入
复制
5
2 1 5 3 4
输出
复制
5 4 3 1 2
说明
2入栈;1入栈;5入栈;5出栈;3入栈;4入栈;4出栈;3出栈;1出栈;2出栈

思路简单就是找到区间的最大值,直接输出,剩下的入栈即可。

#include 
#include 
using namespace std;
const int maxn = 1e6 + 5;
int n, cnt = 0;
int a[maxn], c[maxn * 4], sta[maxn]; //栈和树状数组以及栈
int lowbit(int x){return x & (-x);}

//获得某个区间的最大值
int query(int l, int r){
    int ans=a[r];
    while(l!=r)
    {
        for(--r;r>=l+lowbit(r);r-=lowbit(r))
        {
            ans=max(ans,c[r]);
        }
        ans=max(ans,a[r]);
    }
    return ans;
}

//将x位置修改为p
void update(int x, int p){
    while(x <= n){
        c[x] = a[x];
        for(int i = 1; i < lowbit(x); i<<=1){
            c[x] = max(h[x], c[x - i]);
        }
        x += lowbit(x);
    }
}

void test(){
    n = 9;
    int t[] = {0,1,3,4,8,5,6,9,7,2};
    for(int i = 1; i <= 9; i++){
        update(i, t[i]);
    }
    printf("%d %d %d",query(1, 9), query(5, 5), query(6, 9));

}
int main(){
    scanf("%d", &n);
    for(int i = 1; i <= n; i++){
        int x;
        scanf("%d", &x);
        update(i, x);
    }
    int maxv = n;
    for(int i = 1; i <= n; i++){
        if(a[i] == maxv){           //等于最大值就直接输出
            if(i != n - 1)
                printf("%d ", maxv);
            else printf("%d\n", maxv);
            maxv = query(i, n);     //查询下个区间的最大值
        }else{
            sta[cnt++] = a[i];      //否则入栈;
        }
    }
    //出栈
    for(--cnt; cnt > 0;cnt--){
        printf("%d ", sta[cnt]);
    }
    printf("%d\n", sta[0]);
    return 0;
}

你可能感兴趣的:(算法)