S
o
u
r
c
e
:
Source:
Source:2015 Multi-University Training Contest 3
P
r
o
b
l
e
m
:
Problem:
Problem:给两个长度为n=5e4的序列,A和B,要求在A序列中找一个非递增的子序列,同时这个子序列的下标在B串中非递增。要求这个子序列最长,输出字典序最小的方案。
I
d
e
a
:
Idea:
Idea:经典的三维偏序,CDQ分治。由于要求字典序最小,所以从后往前更新。然后只是前缀最大值的话,直接树状数组维护下就好了。可以维护值最大且标号最小的后继点,也可以只维护最大值,在输出时考虑后继点就好了。
(一些cdq的问题:1.下标各不相同,直接就可以拿来做分治的拿一维。剩下的两维按照其中一维排序后就是二维偏序了。2.如果是先更新完一个区间再更新另一个,下标会被打乱,要重新sort。)
#include<bits/stdc++.h>
using namespace std;
#define lc o<<1
#define rc o<<1|1
#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))
#pragma comment(linker, "/STACK:1024000000,1024000000")
#define DEBUG printf("Passing [%s] in Line %d\n",__FUNCTION__,__LINE__)
using DB = double;
using LL = long long;
using PII = pair<int, int>;
const int N = 1e5+10;
//const LL MOD = 998244353;
//const LL INF = 1e18;
int c[N], dp[N], nxt[N];
inline int query(int x) {
int id = 0;
while(x) {
if(!id || dp[c[x]]>dp[id] || (dp[id]==dp[c[x]]&&id>c[x])) {
id = c[x];
}
x-=(x&-x);
}
return id;
}
inline void add(int x, int id) {
while(x < N) {
if(!c[x] || dp[id]>dp[c[x]] || (dp[id]==dp[c[x]]&&id<c[x])) {
c[x] = id;
}
x+=(x&-x);
}
}
inline void del(int x) { while(x < N) c[x] = 0, x+=(x&-x); }
struct Query {
int x, y, z;
bool operator < (const Query &A) const {
return x==A.x?y>A.y:x<A.x;
}
}q[N], tq[N];
void solve(int L, int R) {
if(L == R) return;
int M = L+R>>1, l1 = L, l2 = M+1;
for(int i = L; i <= R; i++) {
if(q[i].z <= M) tq[l1++] = q[i];
else tq[l2++] = q[i];
}
for(int i = L; i <= R; i++) q[i] = tq[i];
solve(M+1, R);
sort(q+M+1, q+R+1);
int j = R;
for(int i = M; i >= L; i--) {
while(j>M && q[j].x>=q[i].x) add(q[j].y, q[j].z), j--;
int v = query(q[i].y);
int u = q[i].z;
if(dp[v]+1>dp[u] || (dp[v]+1==dp[u]&&v<nxt[u])) {
dp[u] = dp[v]+1;
nxt[u] = v;
}
}
for(int i = R; i > j; i--) del(q[i].y);
solve(L, M);
}
int b[N];
int main() {
int n;
while(~scanf("%d", &n)) {
int m = 0;
for(int i = 1; i <= n; i++) {
scanf("%d", &q[i].y);
b[m++] = q[i].y;
nxt[i] = 0; dp[i] = 1;
}
sort(b, b+m);
m = unique(b, b+m)-b;
for(int i = 1; i <= n; i++) {
q[i].y = lower_bound(b, b+m, q[i].y)-b+1;
scanf("%d", &q[i].x);
q[i].z = i;
}
sort(q+1, q+n+1);
solve(1, n);
int id = 1;
for(int i = 2; i <= n; i++) {
if(dp[i] > dp[id]) id = i;
}
printf("%d\n", dp[id]);
while(id) {
printf("%d%c", id, nxt[id]?' ':'\n');
id = nxt[id];
}
}
return 0;
}