Boring Class 【HDU - 5324】【cdq套cdq+SPFA輸出最長上升子序列】

題目鏈接


  經典三維偏序,求這樣的一個最長上升子序列:x > x'y < y'id < id',其中,id這個很容易被忽略掉。

  然後我們可以直接用外層cdq套內層cdq的方式去解決這個問題了。

  第一維的x直接用sort排序,這裏就不管了,接下去,第二維的y呢,我們用外層cdq去解決,因爲要求一個上升子序列,所以可以先對左區間處理完,然後將左區間的貢獻先給右區間,然後再處理右區間內的左區間,然後逐步這樣往下即可。

  關於輸出答案,也就是要輸出字典序最小的最長上升子序列,我們可以先得到每個點的當前值可以是由前面的哪個id轉移過來的,然後這裏可以用一個vector維護一下,然後推一個spfa求出每個點的下一個最長子序列上的點的最小字典序可以是哪個。

#include <iostream>
#include <cstdio>
#include <cmath>
#include <string>
#include <cstring>
#include <algorithm>
#include <limits>
#include <vector>
#include <stack>
#include <queue>
#include <set>
#include <map>
#include <bitset>
//#include <unordered_map>
//#include <unordered_set>
#define lowbit(x) ( x&(-x) )
#define pi 3.141592653589793
#define e 2.718281828459045
#define INF 0x3f3f3f3f
#define HalF (l + r)>>1
#define lsn rt<<1
#define rsn rt<<1|1
#define Lson lsn, l, mid
#define Rson rsn, mid+1, r
#define QL Lson, ql, qr
#define QR Rson, ql, qr
#define myself rt, l, r
using namespace std;
typedef unsigned long long ull;
typedef unsigned int uit;
typedef long long ll;
const int maxN = 5e4 + 7;
struct node
{
    int x, y, id; int op;
    node(int a=0, int b=0, int c=0):x(a), y(b), id(c) {}
    friend bool operator < (node e1, node e2) { return e1.x == e2.x ? (e1.y == e2.y ? e1.id < e2.id : e1.y < e2.y) : e1.x > e2.x; }
} t[maxN], cop[maxN], b[maxN];
inline bool cmp_y(node e1, node e2) { return e1.y == e2.y ? e1.id < e2.id : e1.y < e2.y; }
int N, ans[maxN];
vector<int> las[maxN];
void CDQ_In(int l, int r)
{
    if(l == r) return;
    int mid = HalF;
    CDQ_In(l, mid); CDQ_In(mid + 1, r);
    int ql = l, qr = mid + 1, pos = l, cnt = 0; vector<int> cid;
    while(ql <= mid || qr <= r)
    {
        if(qr > r || (ql <= mid && b[ql].id <= b[qr].id))
        {
            if(!b[ql].op)
            {
                if(cnt < ans[b[ql].id])
                {
                    cid.clear();
                    cnt = ans[b[ql].id];
                    cid.push_back(b[ql].id);
                }
                else if(cnt == ans[b[ql].id])
                {
                    cid.push_back(b[ql].id);
                }
            }
            cop[pos ++] = b[ql ++];
        }
        else
        {
            if(b[qr].op)
            {
                if(ans[b[qr].id] < cnt + 1)
                {
                    las[b[qr].id].clear();
                    ans[b[qr].id] = cnt + 1;
                    int len = (int)cid.size();
                    for(int i=0; i<len; i++) las[b[qr].id].push_back(cid[i]);
                }
                else if(cnt && ans[b[qr].id] == cnt + 1)
                {
                    int len = (int)cid.size();
                    for(int i=0; i<len; i++) las[b[qr].id].push_back(cid[i]);
                }
            }
            cop[pos ++] = b[qr ++];
        }
    }
    for(int i=l; i<=r; i++) b[i] = cop[i];
}
void cdq(int l, int r)
{
    if(l == r) return;
    int mid = HalF;
    sort(t + l, t + r + 1);
    cdq(l, mid);
    sort(t + l, t + mid + 1, cmp_y);
    sort(t + mid + 1, t + r + 1, cmp_y);
    int ql = l, qr = mid + 1, pos = l;
    while(ql <= mid || qr <= r)
    {
        if(qr > r || (ql <= mid && t[ql].y <= t[qr].y))
        {
            t[ql].op = 0;
            cop[pos ++] = t[ql ++];
        }
        else
        {
            t[qr].op = 1;
            cop[pos ++] = t[qr ++];
        }
    }
    for(int i=l; i<=r; i++) b[i] = cop[i];
    CDQ_In(l, r);
    cdq(mid + 1, r);
}
int dp[maxN];
queue<int> Q;
bool inque[maxN];
void Out_put(int _UP)
{
    while(!Q.empty()) Q.pop();
    for(int i=0; i<=N; i++)
    {
        if(ans[i] == _UP)
        {
            inque[i] = true;
            Q.push(i);
            dp[i] = 0;
        }
        else
        {
            inque[i] = false;
            dp[i] = INF;
        }
    }
    while(!Q.empty())
    {
        int u = Q.front(); Q.pop(); inque[u] = false;
        int len = (int)las[u].size();
        for(int i=0, v; i<len; i++)
        {
            v = las[u][i];
            if(ans[v] == ans[u] - 1)
            {
                if(dp[v] > u)
                {
                    dp[v] = u;
                    if(!inque[v])
                    {
                        inque[v] = true;
                        Q.push(v);
                    }
                }
            }
        }
    }
    int u = dp[0];
    bool fir = true;
    while(u)
    {
        if(!fir) printf(" ");
        printf("%d", u);
        fir = false;
        u = dp[u];
    }
    printf("\n");
}
void init()
{
    for(int i=1; i<=N; i++)
    {
        ans[i] = 1;
        las[i].clear();
        las[i].push_back(0);
    }
}
signed main()
{
    while(scanf("%d", &N) != EOF)
    {
        init();
        for(int i=1; i<=N; i++) scanf("%d", &t[i].x);
        for(int i=1; i<=N; i++) scanf("%d", &t[i].y);
        for(int i=1; i<=N; i++) t[i].id = i;
        sort(t + 1, t + N + 1);
        cdq(1, N);
        int ans_maxx = 0;
        for(int i=1; i<=N; i++) ans_maxx = max(ans_maxx, ans[i]);
        printf("%d\n", ans_maxx);
        Out_put(ans_maxx);
    }
    return 0;
}

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章