题目大意:现有n+m个三元组,每个三元组表示为(xi,yi,zi),对于两个三元组i,j,如果 xi<xj && yi<yj && zi<zj,那么j可以放在i后面。问可以达到的最长链。
思路:如果按x排序,剩下的问题就可以抽象成:给一个二维平面,每个点(a,b)初始值为0,有两种操作 1、将(a,b)点更新为c值 2、询问区间(0-a,0-b)中的最大值。这个问题,可以用二维树状数组做,但是即使优化为最好,空间开销也太大。于是可以用cdq分治做。需要注意的是x相同的处理方式,我这里用的是两棵树状数组处理的。
学习cdq分治,可参见 《从Cash谈一类分治算法的应用》——陈丹琦
//#pragma comment(linker, "/STACK:102400000,102400000")
#include<cstdio>
#include<cstring>
#include<vector>
#include<queue>
#include<cmath>
#include<cctype>
#include<string>
#include<algorithm>
#include<iostream>
#include<ctime>
#include<map>
#include<set>
using namespace std;
#define MP(x,y) make_pair((x),(y))
#define PB(x) push_back(x)
typedef long long LL;
//typedef unsigned __int64 ULL;
/* ****************** */
const int INF=100011122;
const double INFF=1e100;
const double eps=1e-8;
const LL mod=1000000007;
const int NN=300010;
const int MM=1000010;
/* ****************** */
const int limit=1000000;
int aa,bb;
int C = ~(1<<31);
int M = (1<<16)-1;
int rr() {
aa = 36969 * (aa & M) + (aa >> 16);
bb = 18000 * (bb & M) + (bb >> 16);
return (C & ((aa << 16) + bb)) % 1000000;
}
struct node
{
int x,y,z;
bool operator<(const node &tt)const
{
return x<tt.x;
}
}a[NN];
struct node1
{
int x,y,z,id;
bool operator<(const node1 &tt)const
{
if(y!=tt.y)return y<tt.y;
return z>tt.z;
}
}b[NN];
int dp[NN];
int c[2][limit+1];
int lowbit(int x)
{
return x&(-x);
}
void update(int fg,int x,int val)
{
for(;x<=limit;x+=lowbit(x))
c[fg][x]=max(c[fg][x],val);
}
int get_max(int fg,int x)
{
int ans=0;
for(;x>0;x-=lowbit(x))
ans=max(ans,c[fg][x]);
return ans;
}
void clr_update(int fg,int x)
{
for(;x<=limit;x+=lowbit(x))
c[fg][x]=0;
}
void cdq(int l,int r)
{
if(l==r)
{
dp[l]=max(dp[l],1);
return;
}
int mid=(l+r)>>1;
int t,i,cnt=0,tx=a[mid+1].x;
cdq(l,mid);
for(i=l;i<=r;i++)
{
b[cnt].x=a[i].x;
b[cnt].y=a[i].y;
b[cnt].z=a[i].z;
b[cnt].id=i;
cnt++;
}
sort(b,b+cnt);
for(i=0;i<cnt;i++)
{
if(b[i].id<=mid)
{
update(1,b[i].z, dp[ b[i].id ] );
if(b[i].x!=tx)
update(0,b[i].z, dp[ b[i].id ] );
}
else
{
if(b[i].x==tx)
t=get_max(0,b[i].z-1);
else
t=get_max(1,b[i].z-1);
dp[ b[i].id ] = max( dp[ b[i].id ] , t+1 );
}
}
for(i=0;i<cnt;i++)
if(b[i].id<=mid)
{
clr_update(1,b[i].z);
if(b[i].x!=tx)
clr_update(0,b[i].z);
}
cdq(mid+1,r);
}
void solve(int n)
{
int i,ans=0;
sort(a+1,a+1+n);
memset(c,0,sizeof(c));
memset(dp,0,sizeof(dp));
cdq(1,n);
for(i=1;i<=n;i++)
ans=max(ans,dp[i]);
printf("%d\n",ans);
}
int main()
{
int m,n,i;
while(scanf("%d%d%d%d",&m,&n,&aa,&bb)!=EOF)
{
if(m==0 && n==0)break;
for(i=1;i<=m;i++)
{
scanf("%d%d%d",&a[i].x,&a[i].y,&a[i].z);
a[i].x++;
a[i].y++;
a[i].z++;
}
for(i=1;i<=n;i++)
{
a[i+m].x=rr();
a[i+m].y=rr();
a[i+m].z=rr();
a[i+m].x++;
a[i+m].y++;
a[i+m].z++;
}
solve(n+m);
}
return 0;
}