https://www.nowcoder.com/acm/contest/147/G
首先要了解LCS和LIS可以相互转换
题目保证前三个串中每个数最多出现两次 所以拿四串中数的下标和前三个串中的所有相同数的下标组成四维偏序 然后CDQ求解
但是要注意的是 用CDQ求LIS时和普通CDQ不太一样 要先处理左区间内部 再处理左区间对右区间的影响 最后处理右区间内部
比如 1 2 3 4这个例子 如果左右分别处理后再处理当前区间 答案就会是3 可以手动模拟一下
#include <bits/stdc++.h>
using namespace std;
struct node
{
int tp;
int x;
int y;
int z;
int id;
};
node order[80010],tmp1[80010],tmp2[80010];
int pos[10010][3][2];
int book[10010],dp[80010],sum[80010];
int n,tot;
bool cmpI(node n1,node n2)//
{
return n1.x<n2.x;
}
bool cmpII(node n1,node n2)//
{
return n1.y<n2.y;
}
int lowbit(int x)
{
return x&(-x);
}
void update(int tar,int val)
{
int i;
for(i=tar;i<=n;i+=lowbit(i)) sum[i]=max(sum[i],val);
}
void clear(int tar)
{
int i;
for(i=tar;i<=n;i+=lowbit(i)) sum[i]=0;
}
int query(int tar)
{
int res,i;
res=0;
for(i=tar;i>=1;i-=lowbit(i)) res=max(res,sum[i]);
return res;
}
void cdqII(int l,int r)
{
int m,p,q,i;
if(l==r) return;
m=(l+r)/2;
cdqII(l,m);
for(i=l;i<=r;i++) tmp2[i]=tmp1[i];
sort(tmp2+l,tmp2+m+1,cmpII);
sort(tmp2+m+1,tmp2+r+1,cmpII);
p=l,q=m+1;
while(p<=m&&q<=r)
{
if(tmp2[p].y<tmp2[q].y)
{
if(tmp2[p].tp==0) update(tmp2[p].z,dp[tmp2[p].id]);
p++;
}
else
{
if(tmp2[q].tp==1) dp[tmp2[q].id]=max(dp[tmp2[q].id],query(tmp2[q].z-1)+1);
q++;
}
}
while(q<=r)
{
if(tmp2[q].tp==1) dp[tmp2[q].id]=max(dp[tmp2[q].id],query(tmp2[q].z-1)+1);
q++;
}
for(i=l;i<p;i++) if(tmp2[i].tp==0) clear(tmp2[i].z);
cdqII(m+1,r);
}
void cdqI(int l,int r)
{
int m,i;
if(l==r) return;
m=(l+r)/2;
cdqI(l,m);
for(i=l;i<=r;i++)
{
tmp1[i]=order[i];
if(i<=m) tmp1[i].tp=0;
else tmp1[i].tp=1;
}
sort(tmp1+l,tmp1+r+1,cmpI);
cdqII(l,r);
cdqI(m+1,r);
}
int main()
{
int i,j,val,ans;
scanf("%d",&n);
for(j=0;j<3;j++)
{
memset(book,0,sizeof(book));
for(i=1;i<=n;i++)
{
scanf("%d",&val);
if(!book[val]) pos[val][j][0]=pos[val][j][1]=i;
else pos[val][j][1]=i;
book[val]=1;
}
}
tot=0;
for(i=1;i<=n;i++)
{
scanf("%d",&val);
if(!pos[val][0][0]||!pos[val][1][0]||!pos[val][2][0]) continue;
for(j=7;j>=0;j--)
{
++tot;
order[tot].tp=0;
order[tot].x=pos[val][0][j&1];
order[tot].y=pos[val][1][(j>>1)&1];
order[tot].z=pos[val][2][(j>>2)&1];
order[tot].id=tot;
dp[tot]=1;
}
}
cdqI(1,tot);
ans=0;
for(i=1;i<=tot;i++) ans=max(ans,dp[i]);
printf("%d\n",ans);
return 0;
}