題目鏈接
題意:給出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個三維座標由該式子確定。
然後求一個最長上升子序列,使得且不能完全相等,也就是嚴格遞增最長上升子序列。
經典的三維偏序問題。
去重
首先,爲了避免相同這個問題的存在,我們要先離散化一下,並且還要給原來的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
*/