解析:因为是最小字典序,所以从右往左DP。
dp[i] = max(dp[j]+1) i < j,L[i]>=L[j],R[i]<=R[j]
因为这是三维上的问题,自然的就能想到cdq分治了。
在一个区间[l,r]内,先对[mid+1,r]递归,按L[]排序后建立一个对R的线段树,来计算[mid+1,r]的影响,再递归[l,r]。
这里说的比较笼统,不过熟悉cdq分治的同学应该能立马明白我说的什么吧!
[code]:
#include<cstdio>
#include<cstring>
#include<algorithm>
#define lson l,mid,rt<<1
#define rson mid+1,r,rt<<1|1
using namespace std;
const int maxn = 1e5+5;
int mc[2*maxn],hah;
int n,L[maxn],R[maxn],dp[maxn],pre[maxn];
int C[8*maxn];
int que[maxn];
void init(){
hah = 0;
memset(pre,-1,(n+1)*sizeof(int));
}
void push_up(int rt){
if(dp[C[rt<<1]] != dp[C[rt<<1|1]]){
C[rt] = dp[C[rt<<1]]>dp[C[rt<<1|1]]?C[rt<<1]:C[rt<<1|1];
}else C[rt] = min(C[rt<<1],C[rt<<1|1]);
}
void build(int l,int r,int rt){
C[rt] = 0;
if(l == r) return;
int mid = (l+r)>>1;
build(lson);build(rson);
}
void update(int k,int x,int l,int r,int rt){
if(l == r){
if(dp[x]>dp[C[rt]]) C[rt] = x;
else if(dp[x]==dp[C[rt]]) C[rt] = min(C[rt],x);
return;
}
int mid = (l+r)>>1;
if(k <= mid) update(k,x,lson);
else update(k,x,rson);
push_up(rt);
}
void debug(int l,int r,int rt){
if(l ==r){
printf("%d ",C[rt]);
return;
}
int mid = (l+r)>>1;
debug(lson);debug(rson);
}
void clr(int k,int l,int r,int rt){
C[rt] = 0;
if(l == r) return;
int mid = (l+r)>>1;
if(k <= mid) clr(k,lson);
else clr(k,rson);
}
int query(int a,int b,int l,int r,int rt){
if(a <= l&&r <= b) return C[rt];
if(l > b||r < a) return 0;
int p1,p2,mid = (l+r)>>1;
p1 = query(a,b,lson);p2 = query(a,b,rson);
if(dp[p1]!=dp[p2]) return dp[p1]>dp[p2]?p1:p2;
else return min(p1,p2);
}
bool cmp(const int &i,const int &j){
return L[i]!=L[j]?L[i]<L[j]:i > j;
}
void cdq(int l,int r){
if(l>=r) return;
int u,v,i,j,mid,len;
mid = (l+r)>>1;
cdq(mid+1,r);
len = 0;
for(i = l;i <= r;i++) que[len++] = i;
sort(que,que+len,cmp);
for(i = 0;i < len;i++){
u = que[i];
if(u > mid){
update(R[u],u,1,hah,1);
}else{
v = query(R[u],hah,1,hah,1);
if(!v) continue;
if(dp[u]<dp[v]+1){
dp[u] = dp[v]+1;pre[u] = v;
}else if(dp[u]==dp[v]+1) pre[u] = min(pre[u],v);
}
}
for(i = 0;i < len;i++){
if(que[i]>mid) clr(R[que[i]],1,hah,1);
}
cdq(l,mid);
}
int main(){
int i,j;
while(~scanf("%d",&n)){
init();
for(i = 1;i <= n;i++) scanf("%d",&L[i]);
for(i = 1;i <= n;i++) scanf("%d",&R[i]);
for(i = 1;i <= n;i++){
mc[hah++] = L[i];mc[hah++] = R[i];
dp[i] = 1;
}
sort(mc,mc+hah);
hah = unique(mc,mc+hah)-mc;
for(i = 1;i <= n;i++){
L[i] = lower_bound(mc,mc+hah,L[i])-mc+1;
R[i] = lower_bound(mc,mc+hah,R[i])-mc+1;
}
build(1,hah,1);
cdq(1,n);
int tmp = -1;
for(i = 1;i <= n;i++){
tmp = max(tmp,dp[i]);
}
for(i = 1;i <= n;i++) if(dp[i]==tmp) break;
printf("%d\n%d",dp[i],i);
while(pre[i]!=-1){
printf(" %d",pre[i]);
i = pre[i];
}
putchar('\n');
}
return 0;
}