Boring Class
Time Limit: 6000/3000 MS (Java/Others) Memory Limit: 65536/65536 K (Java/Others)Total Submission(s): 255 Accepted Submission(s): 53
Problem Description
Mr. Zstu and Mr. Hdu are taking a boring class , Mr. Zstu comes up with a problem to kill time, Mr. Hdu thinks it’s too easy, he solved it very quickly, what about you guys?
Here is the problem:
Give you two sequences L1,L2,...,Ln and R1,R2,...,Rn .
Your task is to find a longest subsequence v1,v2,...vm satisfies
v1≥1 , vm≤n , vi<vi+1 .(for i from 1 to m - 1)
Lvi≥Lvi+1 , Rvi≤Rvi+1 (for i from 1 to m - 1)
If there are many longest subsequence satisfy the condition, output the sequence which has the smallest lexicographic order.
Here is the problem:
Give you two sequences L1,L2,...,Ln and R1,R2,...,Rn .
Your task is to find a longest subsequence v1,v2,...vm satisfies
v1≥1 , vm≤n , vi<vi+1 .(for i from 1 to m - 1)
Lvi≥Lvi+1 , Rvi≤Rvi+1 (for i from 1 to m - 1)
If there are many longest subsequence satisfy the condition, output the sequence which has the smallest lexicographic order.
![](https://i-blog.csdnimg.cn/blog_migrate/93a8a6b9c26c0d4866d2e6a76b03b9fd.jpeg)
Input
There are several test cases, each test case begins with an integer n.
1≤n≤50000
Both of the following two lines contain n integers describe the two sequences.
1≤Li,Ri≤109
1≤n≤50000
Both of the following two lines contain n integers describe the two sequences.
1≤Li,Ri≤109
Output
For each test case ,output the an integer m indicates the length of the longest subsequence as described.
Output m integers in the next line.
Output m integers in the next line.
Sample Input
5 5 4 3 2 1 6 7 8 9 10 2 1 2 3 4
Sample Output
5 1 2 3 4 5 1 1
Source
这道题是经典的树套树,外面用树状数组,里面套Treap树。一维树状数组节点先要对数据离散化,第二维Treap节点维护一个mlen和midx统计所有该节点左孩子、右孩子和自己DP最优值。空间是动态分配的,由于n次查找,每次对树状数组上的logn个一维结点查询,每次最多往每个一维结点中插入一个二维Treap结点,空间的总开销为n*logn,时间是n*logn*logn。
从数组的右边往左边做DP,可以保证字典序最小。时间比较慢1500ms。
#include <iostream>
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <algorithm>
using namespace std;
const int maxn = 50010;
struct Node{
Node *ch[2];
int r;
int v; //第二维
int len; //长度
int idx; //下标
int mlen; //结点和结点左孩子右孩子里最大长度
int midx; //结点和结点左孩子右孩子里最大长度对应的下标
Node() {}
Node(int v, int len, int idx):v(v),len(len),idx(idx),mlen(len),midx(idx) {ch[0] = ch[1] = NULL; r = rand();}
int cmp(int x) const {
if (x == v) return -1;
return x < v ? 0 : 1;
}
void maintain(){
mlen = len;
midx = idx;
if (ch[0] != NULL && (ch[0]->mlen > mlen || (ch[0]->mlen == mlen && ch[0]->midx < midx))){
mlen = ch[0]->mlen;
midx = ch[0]->midx;
}
if (ch[1] != NULL && (ch[1]->mlen > mlen || (ch[1]->mlen == mlen && ch[1]->midx < midx))){
mlen = ch[1]->mlen;
midx = ch[1]->midx;
}
}
};
bool findMax(Node* a, Node* b){
if (a->mlen < b->mlen || (a->mlen == b->mlen && a->midx > b->midx)){
*a = *b;
return true;
}
return false;
}
namespace Treap{
int cntnode;
Node node[maxn*10];
void init(){
cntnode = 0;
}
Node* newNode(int v, int len, int idx){
node[++cntnode] = Node(v, len, idx);
return &node[cntnode];
}
void rotate(Node* &o, int d){
Node* k = o->ch[d^1]; o->ch[d^1] = k->ch[d]; k->ch[d] = o;
o->maintain(); k->maintain(); o = k;
}
void insert(Node* &o, int v, int len, int idx){
if (o == NULL) o = newNode(v, len, idx);
else {
int d = o->cmp(v);
if (d != -1){
insert(o->ch[d], v, len, idx);
if (o->r < o->ch[d]->r) rotate(o, d^1);
}
else
{
if (len >= o->len){
o->len = len;
o->idx = idx;
}
}
}
o->maintain();
}
Node search(Node *o, int v){
if (o == NULL){
return Node(-1, 0, -1);
}
else{
Node re, tmp;
if (o->v == v) {
re = Node(o->v, o->len, o->idx);
if (o->ch[1]){
findMax(&re, o->ch[1]);
}
}
else if (o->v > v){
re = Node(o->v, o->len, o->idx);
if (o->ch[1]){
findMax(&re, o->ch[1]);
}
if (o->ch[0]){
tmp = search(o->ch[0], v);
findMax(&re, &tmp);
}
}
else{
re = search(o->ch[1], v);
}
return re;
}
}
}
namespace BIT{
Node* fwt[maxn];
int N;
void init(int n){
N = n;
memset(fwt, 0, sizeof fwt);
}
void add(int v1, int v2, int len, int idx){
while(v1 < N){
Treap::insert(fwt[v1], v2, len, idx);
v1 += (-v1)&v1;
}
}
Node query(int v1, int v2){
Node re, tmp;
re = Node(-1, 0, -1);
while(v1 > 0){
tmp = Treap::search(fwt[v1], v2);
findMax(&re, &tmp);
v1 -= (-v1)&v1;
}
return re;
}
}
struct Pe{
int L,R;
int i;
bool operator < (const Pe& rhs)const{
return L < rhs.L;
}
};
bool cmp(Pe a, Pe b){
return a.i < b.i;
}
int solo[maxn];
Pe pe[maxn];int pre[maxn];
void print(Node& a){
int id = a.midx;
printf("%d\n", a.mlen);
while(1){
printf("%d", id+1);
if (pre[id] == -1){
break;
}
printf(" ");
id = pre[id];
}
printf("\n");
}
int main(){
int n;
while(scanf("%d", &n) != EOF){
for(int i=0;i<n;i++){
pe[i].i = i;
scanf("%d", &pe[i].L);
}
for(int i=0;i<n;i++){
scanf("%d", &pe[i].R);
}
sort(pe, pe+n);
int m = 0;
solo[0] = ++m;
for(int i=1;i<n;i++){
if (pe[i].L != pe[i-1].L){
solo[i] = ++m;
}
else{
solo[i] = solo[i-1];
}
}
for(int i=0;i<n;i++){
pe[i].L = solo[i];
}
sort(pe, pe+n, cmp);
BIT::init(m+1);
Treap::init();
Node ans = Node(-1, 0, -1), tmp;
for(int i=n-1;i>=0;i--){
tmp = BIT::query(pe[i].L, pe[i].R);
pre[i] = tmp.midx;
tmp.mlen = tmp.mlen + 1;
tmp.midx = i;
BIT::add(pe[i].L, pe[i].R, tmp.mlen, tmp.midx);
findMax(&ans, &tmp);
}
print(ans);
}
return 0;
}