樹狀數組維護區間最值

題目描述
給你一個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 <stdio.h>
#include <iostream>
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;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章