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
*/

 

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