题意:三维偏序LIS的最小字典序答案。
分治的时候逆着做就可以了。
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#include <cmath>
using namespace std;
#define maxn 100005
#define mod (1LL<<30)
#define INF 111111111
struct node {
int id;
int x, y;
bool operator == (const node &a) const {
return x == a.x && y == a.y;
}
}qu[maxn], tmp[maxn];
struct Node {
int len, id;
} ans[maxn], c[maxn];
int n;
bool cmp2 (const node &a, const node &b) {
return a.x < b.x || (a.x == b.x && a.y > b.y);
}
int lowbit (int x) {
return x&(-x);
}
void judge (Node &a, Node b) {
if (a.len < b.len)
a = b;
else if (a.len == b.len && a.id > b.id)
a = b;
}
void update (int x, Node tmp) {
for (int i = x; i < maxn; i += lowbit (i)) {
judge (c[i], tmp);
}
}
Node query (int x) {
Node ans = (Node) {0, INF};
for (int i = x; i > 0; i -= lowbit (i)) {
judge (ans, c[i]);
}
return ans;
}
void clear (int x) {
for (int i = x; i < maxn; i += lowbit (i))
c[i] = (Node) {0, INF};
}
void solve (int l, int r) {
if (l == r)
return ;
int mid = (l+r)>>1;
solve (mid+1, r);
for (int i = l; i <= r; i++) {
tmp[i] = qu[i];
}
sort (tmp+l, tmp+mid+1, cmp2);
sort (tmp+mid+1, tmp+r+1, cmp2);
int R = r;
for (int i = mid; i >= l; i--) {
while (R > mid && tmp[R].x >= tmp[i].x) {
update (tmp[R].y, (Node) {ans[tmp[R].id].len, tmp[R].id});
R--;
}
Node cur = query (tmp[i].y);
cur.len++;
judge (ans[tmp[i].id], cur);
}
for (int i = l; i <= r; i++) clear (tmp[i].y);
solve (l, mid);
}
int num[maxn], tot;
int gg[maxn];
void lisanhua () {
sort (num, num+tot);
int cnt = 0;
for (int i = 0; i < tot; i++) {
if (!i || num[i] != num[i-1]) gg[cnt++] = num[i];
}
for (int i = 1; i <= n; i++) {
qu[i].y = lower_bound (gg, gg+cnt, qu[i].y)-gg+1;
}
}
int scan () {
char ch=' ';
while(ch<'0'||ch>'9')ch=getchar();
int x=0;
while(ch<='9'&&ch>='0')x=x*10+ch-'0',ch=getchar();
return x;
}
int main () {
while (scanf ("%d", &n) == 1) {
tot = 0;
for (int i = 1; i <= n; i++) scanf ("%d", &qu[i].y), qu[i].id = i, num[tot++] = qu[i].y;
for (int i = 1; i <= n; i++) scanf ("%d", &qu[i].x);
for (int i = 1; i <= n; i++) ans[i] = (Node) {1, i}, c[i] = (Node) {0, INF};
lisanhua ();
solve (1, n);
int Max = 0;
for (int i = 1; i <= n; i++) {
Max = max (ans[i].len, Max);
}
printf ("%d\n", Max);
for (int i = 1; i <= n; i++) if (ans[i].len == Max) {
while (ans[i].id != i) {
printf ("%d ", i);
i = ans[i].id;
}
printf ("%d\n", i);
break;
}
}
return 0;
}