Coronavirus Battle【CDQ套CDQ】【2020 年 “遊族杯” 全國高校程序設計網絡挑戰賽 C】

題目鏈接


  題意:給出N個三維座標,輸入按照題意的這個給出:

ull CoronavirusBeats()
{
    ull k3 = k1, k4 = k2;
    k1 = k4;
    k3 ^= k3 << 23;
    k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
    return k2 + k4;
}

  只有一個N,和K1和K2,然後N個三維座標由該式子確定。

  然後求一個最長上升子序列,使得x\leq x', y\leq y', z\leq z'且不能完全相等,也就是嚴格遞增最長上升子序列。

  經典的三維偏序問題。

去重

  首先,爲了避免相同這個問題的存在,我們要先離散化一下,並且還要給原來的1~N標記現在對應離散過後的哪個點,並且要給新的點也打上標記,因爲做cdq的時候會打亂順序的。

cdq(外圍)

  外圍的cdq,首先在分治進行之前,會保證x已經按照升序拍好了,所以這一維的cdq要讓y按照升序排好。並且,這一維的cdq跟平時需要有不一樣的地方,就是我們需要先cdq左區間,然後直接將左區間對右區間的貢獻算出來,然後再對右區間進行處理,因爲我們需要保證是一個最長上升,所以有的右區間的點要先繼承了左區間的,再對右區間這側的點進行貢獻,而不是直接貢獻。

套cdq(內層)

  內層的cdq分治,就是一個基礎的cdq分治了,直接求外層cdq對內層cdq的左對右造成的貢獻,是個基礎的內層cdq寫法。

#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;
ull k1, k2;
ull CoronavirusBeats()
{
    ull k3 = k1, k4 = k2;
    k1 = k4;
    k3 ^= k3 << 23;
    k2 = k3 ^ k4 ^ (k3 >> 17) ^ (k4 >> 26);
    return k2 + k4;
}
const int maxN = 1e5 + 7;
//const int maxN = 8;
int N, tot, K, ans[maxN];
struct node
{
    ull x, y, z; int sum, op, id;   //sum是相同元素的個數
    node(ull a=0, ull b=0, ull c=0, int d=0):x(a), y(b), z(c), sum(d) {}
    friend bool operator < (node e1, node e2) { return e1.x == e2.x ? (e1.y == e2.y ? e1.z < e2.z : e1.y < e2.y) : e1.x < e2.x; }
    friend bool operator == (node e1, node e2) { return e1.x == e2.x && e1.y == e2.y && e1.z == e2.z; }
}q[maxN], cop[maxN], b[maxN];
bool cmp_y(node e1, node e2) { return e1.y < e2.y; }
int _ID[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;
    while(ql <= mid || qr <= r)
    {
        if(qr > r || (ql <= mid && b[ql].z <= b[qr].z))
        {
            if(!b[ql].op) cnt = max(cnt, ans[b[ql].id]);
            cop[pos++] = b[ql++];
        }
        else
        {
            if(b[qr].op) ans[b[qr].id] = max(ans[b[qr].id], cnt + 1);
            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(q + l, q + r + 1);
    cdq(l, mid);
    sort(q + l, q + mid + 1, cmp_y);
    sort(q + mid + 1, q + r + 1, cmp_y);
    int ql = l, qr = mid + 1, pos = l;
    while(ql <= mid || qr <= r)
    {
        if(qr > r || (ql <= mid && q[ql].y <= q[qr].y))
        {
            q[ql].op = 0;
            cop[pos++] = q[ql++];
        }
        else
        {
            q[qr].op = 1;
            cop[pos++] = q[qr++];
        }
    }
    for(int i=l; i<=r; i++) b[i] = cop[i];
//    for(int i=l; i<=r; i++) q[i] = cop[i];
    CDQ_In(l, r);
    cdq(mid + 1, r);
}
signed main()
{
    scanf("%d%llu%llu", &N, &k1, &k2);
    for(int i=1; i<=N; i++)
    {
        cop[i].x = CoronavirusBeats();
        cop[i].y = CoronavirusBeats();
        cop[i].z = CoronavirusBeats();
        cop[i].id = i;
//        printf("%21llu %21llu %21llu\n", cop[i].x, cop[i].y, cop[i].z);
    }
    sort(cop + 1, cop + N + 1);
    tot = 1;
    q[1] = cop[1];
    q[1].id = 1;
    _ID[cop[1].id] = 1;
    for(int i=2; i<=N; i++)
    {
        if(cop[i] == cop[i - 1]) { _ID[cop[i].id] = tot; continue; }
        q[tot].sum = 1;
        q[++tot] = cop[i];
        q[tot].id = tot;
        _ID[cop[i].id] = tot;
    }
    q[tot].sum = 1;
    for(int i=1; i<=tot; i++) ans[i] = 1;
    cdq(1, tot);
    int maxx = 0;
    for(int i=1; i<=tot; i++)
    {
        maxx = max(maxx, ans[i]);
    }
    printf("%d\n", maxx);
    for(int i=1; i<=N; i++) printf("%d%c", ans[_ID[i]] - 1, i == N ? '\n' : ' ');
    return 0;
}
/*
7 1 0
ans:0 1 2 2 4 3 4
*/

 

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