HDU 5324 Boring Class 树套树 或 CDQ分治
题目链接:HDU 5324
题意:
给定两个序列,求一个最长的公共子序列使得第一个子序列递减,第二个递增。
思路:
将L数组的下标排序并从小到大插入,维护一个满足R的最大DP值的位置。二维。如果内存够大可以,线段树套线段树,可以用线段树套SPLAY。
代码:
#include <cstdio>
#include <cstring>
#include <algorithm>
#include <iostream>
#define Lson o<<1,l,mid
#define Rson o<<1|1,mid+1,r
#define MID int mid=(l+r)>>1
using namespace std;
const int maxn = 50010;
int dp[maxn];
int data[maxn][2];
int ans[maxn];
int anse;
void read(int& a){
char c;
while(c=getchar(),c<'0'||c>'9');
a=c-'0';
while(c=getchar(),c>='0'&&c<='9')
a=a*10+c-'0';
}
int max1(int a,int b){
if(dp[a]==dp[b])return a<b?a:b;
return dp[a]>dp[b]?a:b;
}
namespace splay_tree{
const int SPLAYSIZE=1501000;
#define NIL splay_pool
struct SNode{
int val,mpos,pos;
SNode *lch,*rch,*fa;
SNode (){
val=0;
lch=rch=fa=0;
pos=mpos=0;
}
SNode (int _val,SNode *_lch,SNode *_rch,SNode *_fa)
:val(_val),lch(_lch),rch(_rch),fa(_fa){
pos=mpos=0;
}
}splay_pool[SPLAYSIZE];
SNode *SP;
struct Splay{
SNode *root,*head,*tail;
Splay(){}
void init(){
head=new(++SP)SNode(-2000000000,NIL,NIL,NIL);
tail=new(++SP)SNode(2000000000,NIL,NIL,NIL);
head->rch=tail;
tail->fa=head;
root=head;
}
void update(SNode *t){
if(t==NIL)return;
t->mpos=max1(t->pos,max1(t->lch->mpos,t->rch->mpos));
}
void zig(SNode *t){
SNode *f=t->fa,*c=t->rch;
if(root==f) root=t;
else {(f->fa->lch==f?f->fa->lch:f->fa->rch)=t;}
t->fa=f->fa,t->rch=f, f->lch=c, f->fa=t, c->fa=f;
update(f),update(t);
}
void zag(SNode *t){
SNode *f=t->fa,*c=t->lch;
if(root==f)root=t;
else (f->fa->lch==f?f->fa->lch:f->fa->rch)=t;
t->fa=f->fa,t->lch=f,f->rch=c,f->fa=t,c->fa=f;
update(f),update(t);
}
void splay(SNode *&root,SNode *t){
while(t!=root){
if(t->fa==root){
if(t->fa->lch==t)zig(t);
else zag(t);
}
else {
if(t->fa->fa->lch==t->fa){
if(t->fa->lch==t)zig(t->fa),zig(t);
else zag(t),zig(t);
}
else {
if(t->fa->lch==t)zig(t),zag(t);
else zag(t->fa),zag(t);
}
}
}
}
void insert(int v,int pp){
SNode *t=root,*p=new(++SP)SNode(v,NIL,NIL,NIL);
p->pos=p->mpos=pp;
while(1){
if(t->val>p->val){
if(t->lch==NIL)break;
t=t->lch;
}
else {
if(t->rch==NIL)break;
t=t->rch;
}
}
(t->val>p->val?t->lch:t->rch)=p,p->fa=t;
splay(root,p);
}
bool lower_bound(SNode *&root,int v){
SNode *t=root,*p=NIL;
while(t!=NIL){
if(t->val<v)p=t,t=t->rch;
else t=t->lch;
}
if(p==NIL){
return false;
}
else {
splay(root,p);
return true;
}
}
void get(int r){
if(anse==max1(anse,root->mpos))
return ;
lower_bound(root,r);
anse=max1(root->rch->mpos,anse);
}
};
}
namespace SGM{
splay_tree::Splay maxv[maxn*4];
void quarry(int o,int l,int r,int L,int R,int val){
if(L<=l&&r<=R){
maxv[o].get(val);
return;
}
MID;
if(L<=mid)quarry(Lson,L,R,val);
if(R>mid) quarry(Rson,L,R,val);
}
void insert(int o,int l,int r,int pos,int val){
maxv[o].insert(val,pos);
if(l==r) return;
MID;
if(pos<=mid)insert(Lson,pos,val);
if(pos>mid) insert(Rson,pos,val);
}
void init(){
dp[0]=0;
for(int i=1;i<maxn;i++)dp[i]=1;
splay_tree::SP=splay_tree::splay_pool;
splay_tree::NIL->lch=splay_tree::NIL->rch=splay_tree::NIL->fa=splay_tree::NIL;
for(int i=1;i<maxn*4;i++){
maxv[i].init();
}
}
}
void init(){
}
int rk[maxn];
bool cmp(int a,int b){
return data[a][0]>data[b][0];
}
int main(){
// freopen("1000.in","r",stdin);
// freopen("data.out","w",stdout);
int n;
while(~scanf("%d",&n)){
init();
for(int i=1;i<=n;i++){
read(data[i][0]);
}
for(int i=1;i<=n;i++){
read(data[i][1]);
rk[i]=i;
}
sort(rk+1,rk+1+n,cmp);
SGM::init();
SGM::insert(1,1,n,rk[n],data[rk[n]][1]);
ans[rk[n]]=0;
for(int i=n-1;i;i--){
anse=0;
SGM::quarry(1,1,n,rk[i],n,data[rk[i]][1]);
ans[rk[i]]=anse;
dp[rk[i]]+=dp[anse];
SGM::insert(1,1,n,rk[i],data[rk[i]][1]);
}
int maxe=0;
for(int i=1;i<=n;i++){
if(dp[i]>dp[maxe]){
maxe=i;
}
}
printf("%d\n",dp[maxe]);
for(int i=maxe;i;i=ans[i]){
if(i!=maxe)putchar(' ');
printf("%d",i);
}
puts("");
}
return 0;
}