这道题十分阴险啊。。
一般来说看到这道题都会选择打一个最长上升子序列的模板吧(比较时就比较三个参数)。。。。
但你可以看到,5,6,7,8四个点m达到了1e6的规模,那么n^2的复杂的肯定是过不了的。
又可以惊奇的发现,1~8个点的z都为0!
于是经过仔(can)细(kao)思(ti)考(jie)后,1~8个点发现咱可以用树状数组维护DP转移,使其复杂度降到O(nlogn)。
而剩下俩个点 m <= 1e3直接 pi<pj 就连一条 i->j 的边 spfa跑最长链就可以了。
树状数组用得很巧妙,首先z已经为0了,不管它,将x从小到大把卡牌排一遍,然后以y为准进行转移。
那么可以知道,当yi > yj 时,yi处的 f[i] 可以由 f[j] 转移而来,于是我们把y值当做序号,小的放在树状数组前面,大的放在树状数组后面,依次ask并updata求最大值就好了(。。表达不太清楚请看代码)
代码:
#include<bits/stdc++.h>
using namespace std;
const int MAXN = 1e6 + 5;
#define ll long long
#define pt putchar
#define ex pt('\n')
#define ko pt(' ')
int n;
int ans = 1;
bool z0 = 1;
int head[MAXN<<1],cnt = 0;
int dis[MAXN];
struct edge
{
int next,to;
}e[MAXN<<1];
void add(int u,int v)
{
e[++cnt].next = head[u]; e[cnt].to = v; head[u] = cnt;
}
void in(int &x)
{
int num = 0,f = 1; char ch = getchar();
while(ch < '0' || ch > '9') {if(ch == '-') f = -1; ch = getchar();}
while(ch >= '0' && ch <= '9') {num = (num<<3) + (num<<1) + (ch-'0'); ch = getchar();}
x = num*f;
}
void out(int x)
{
if(x < 0) x = -x,pt('-');
if(x > 9) out(x/10);
pt(x%10 + '0');
}
struct card
{
int x,y,z;
bool operator < (const card one) const
{
if(x != one.x) return x < one.x;
return y < one.y;
}
}c[MAXN];
ll f[MAXN];
int lowbit(int x) {return x&-x;}
void updata(int x,ll v)
{
while(x < MAXN)
{
f[x] = max(v,f[x]);
x += lowbit(x);
}
}
int ask(int x)
{
ll res = 0;
while(x)
{
res = max(f[x],res);
x -= lowbit(x);
}
return res;
}
inline void init()
{
in(n);
for(int i = 1;i <= n;i++)
{
in(c[i].x),in(c[i].y),in(c[i].z);
if(c[i].z != 0) z0 = 0;
}
}
void work1()
{
sort(c+1,c+n+1);
for(int i = 1;i <= n;i++)
{
int tmp = ask(c[i].y) + 1;
ans = max(ans,tmp);
updata(c[i].y,tmp);
}
}
bool check(int i,int j)
{
if(c[i].x <= c[j].x && c[i].y <= c[j].y && c[i].z <= c[j].z) return 1;
return 0;
}
int q[MAXN<<1];
bool vis[MAXN];
void spfa(int st)
{
int h = 0,t = 0;
memset(vis,0,sizeof vis);
q[++t] = st; vis[st] = 1;
while(h < t)
{
int x = q[++h];
for(int i = head[x];i;i = e[i].next)
{
int to = e[i].to;
if(vis[to]) continue;
if(dis[x] + 1 > dis[to])
{
vis[to] = 1;
dis[to] = dis[x] + 1;
q[++t] = to;
}
}
}
for(int i = 1;i <= n;i++) ans = max(ans,dis[i]);
}
void work2()
{
for(int i = 1;i <= n;i++)
for(int j = 1;j <= n;j++)
if(check(i,j) && i != j) add(i,j);
for(int i = 1;i <= n;i++) spfa(i);
ans++;
}
int main()
{
init();
if(c[1].y == 0) {cout << n; return 0;}
if(z0) work1();
else work2();
out(ans);
return 0;
}
/*
4
5 7 6
1 3 4
5 4 4
3 3 8
*/