HDU 4604 (樹狀數組)

題目鏈接:點擊這裏

題意:給出一個序列,從頭到尾依次扔進一個雙端隊列或者直接不要,雙端隊列可以在任意時刻從頭或者尾彈出元素。最大化最後的雙端隊列size。

求出每個下標開頭的最長遞增序列和最長遞減序列,然後掃一遍用樹狀數組維護即可。

#include <cstdio>
#include <cstring>
#include <cmath>
#include <algorithm>
#include <vector>
#include <queue>
#include <iostream>
using namespace std;
#define maxn 100005

int dp[maxn], dp2[maxn];//以i開頭的最長遞增子序列 以i開頭的最長遞減子序列
int c[maxn], a[maxn], n;
vector <int> num;
int gg[maxn], cnt;

void lisanhua () {//離散化
    sort (num.begin (), num.end ());
    for (int i = 0; i < n; i++) {
        if (!i || num[i] != num[i-1]) {
            gg[++cnt] = num[i];
        }
    }
    for (int i = 1; i <= n; i++) { 
        a[i] = lower_bound (gg+1, gg+1+cnt, a[i])-gg;
    }
}

int lowbit (int x) {
    return x&(-x);
}

void update1 (int pos, int num) {
    for (int i = pos; i > 0; i -= lowbit (i))
        c[i] = max (c[i], num);
}

void update2 (int pos, int num) {
    for (int i = pos; i <= n; i += lowbit (i))
        c[i] = max (c[i], num);
}

int query_max (int pos) {
    int ans = 0;
    for (int i = pos; i <= n; i += lowbit (i)) {
        ans = max (ans, c[i]);
    }
    return ans;
}

int query_min (int pos) {
    int ans = 0;
    for (int i = pos; i > 0; i -= lowbit (i)) {
        ans = max (ans, c[i]);
    }
    return ans;
}

void solve () {
    memset (c, 0, sizeof c);
    for (int i = n; i >= 1; i--) {
        dp[i] = query_max (a[i])+1;
        update1 (a[i], dp[i]);
    }
    memset (c, 0, sizeof c);
    for (int i = n; i >= 1; i--) {
        dp2[i] = query_min (a[i])+1;
        update2 (a[i], dp2[i]);
    }
    int ans = 0;
    for (int i = 1; i <= n; i++) {
        int tmp = query_min (a[i]-1); 
        ans = max (ans, tmp+dp[i]);
    }
    printf ("%d\n", ans);
}

int main () {
    //freopen ("more.in", "r", stdin);
    int t;
    scanf ("%d", &t);
    while (t--) {
        scanf ("%d", &n);
        cnt = 0;
        num.clear ();
        for (int i = 1; i <= n; i++) {
            scanf ("%d", &a[i]);
            num.push_back (a[i]);
        }
        lisanhua ();
        solve ();
    }
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章