s
o
u
r
c
e
:
source:
source:牛客网暑期ACM多校训练营(第九场)
p
r
o
b
l
e
m
:
problem:
problem:
n
=
1
e
4
n=1e4
n=1e4,求四个序列的最长公共子序列。前三个序列每个数不会出现超过两次。
I
d
e
a
:
Idea:
Idea:每个数在不同序列中的下标构成的元素
(
p
a
,
p
b
,
p
c
,
p
d
)
(pa,pb,pc,pd)
(pa,pb,pc,pd)的四维偏序问题,总共只有
8
n
8n
8n个元素。
C
o
d
e
:
Code:
Code:
//CDQ*2+BIT
void CDQ(int v, int cnt) {
for(int i = 0; i < cnt; i++) {
if(!q[v][i].f) add(q[v][i].d[v+1], *q[v][i].v);
else umax(*q[v][i].v, sum(q[v][i].d[v+1]-1)+1);
}
for(int i = 0; i < cnt; i++) if(!q[v][i].f) del(q[v][i].d[v+1]);
}
//CDQ*3,虽然每一层都多了一个sort,但是这样写方便。
#include<bits/stdc++.h>
using namespace std;
#define Toocold
#define I inline
#define fi first
#define se second
#define pb push_back
#define ALL(X) (X).begin(), (X).end()
#define bcnt(X) __builtin_popcountll(X)
#define CLR(A, X) memset(A, X, sizeof(A))
using DB = double;
//using DB = long double;
using LL = long long;
using ULL = unsigned long long;
using PII = pair<int, int>;
#ifdef Toocold
#define dbg(args...)\
do { cout << "DEBUG: " << #args << " -> "; err(args); } while(0)
#else
#define dbg(...)
#endif // Toocold
void err() { puts(""); }
template<template<typename...> class T, typename t, typename... Args>
void err(T<t> a, Args... args) { for(auto x:a) cout << x << ' '; err(args...); }
template<typename T, typename... Args>
void err(T a, Args... args) { cout << a << ' '; err(args...); }
/*-----------------------------------------------------------------------------*/
const int N = 8e4+10;
I void umax(int &a, const int &b) { if(a < b) a = b; }
int dp[N];
vector<int> G[4][N];
struct meow {
bool f;
int d[5], *v;
}q[5][N];
struct cmp {
int x;
bool operator()(const meow &A, const meow &B) { return A.d[x]==B.d[x]?A.f>B.f:A.d[x]<B.d[x]; }
};
void CDQ(int v, int cnt) {
int t = 0;
for(int i = 0; i < cnt; i++) {
if(!q[v][i].f) umax(t, *q[v][i].v);
else umax(*q[v][i].v, t+1);
}
}
void CDQ(int v, int L, int R) {
if(q[v][L].d[v] == q[v][R].d[v]) return;
int M = (L+R)>>1, l = M, r = M+1, k = 0;
for(; r<=R && q[v][l].d[v]==q[v][r].d[v]; l--, r++);
M = r<=R ? r-1 : l;
CDQ(v, L, M);
for(int i = L; i <= M; i++) {
if(v == 0) q[v+1][k] = q[v][i], q[v+1][k++].f = 0;
else if(!q[v][i].f) q[v+1][k++] = q[v][i];
}
for(int i = M+1; i <= R; i++) {
if(v == 0) q[v+1][k] = q[v][i], q[v+1][k++].f = 1;
else if(q[v][i].f) q[v+1][k++] = q[v][i];
}
if(k) {
sort(q[v+1], q[v+1]+k, cmp{v+1});
if(v+1 == 3) CDQ(v+1, k);
else CDQ(v+1, 0, k-1);
}
CDQ(v, M+1, R);
}
I void work() {
int n; scanf("%d", &n);
for(int i = 0; i < 4; i++)
for(int j = 1; j <= n; j++) {
int x; scanf("%d", &x);
G[i][x].pb(j);
}
int k = 0;
for(int i = 1; i <= n; i++) {
for(int &a:G[3][i]) for(int &b:G[2][i])
for(int &c:G[1][i]) for(int &d:G[0][i]) {
q[0][k].d[0] = a, q[0][k].d[1] = b;
q[0][k].d[2] = c, q[0][k].d[3] = d;
q[0][k].v = &dp[k]; dp[k++] = 1;
}
}
sort(q[0], q[0]+k, cmp{0});
CDQ(0, 0, k-1);
int ans = 0;
for(int i = 0; i < k; i++) {
umax(ans, dp[i]);
}
printf("%d\n", ans);
}
int main() {
work();
return 0;
}