好像上去讲的有点快,主要是本身就挺短,,这里讲的会详细一点。
题意很明显就不说了。
题意就不说了,注意线段上的点是不能选的。
首先要明确一个东西,这里说是双向链表维护,是因为我们维护了一个点的前驱后继,这符合双向链表的定义,但是实际上大家把他当作普通数组一样维护就好了。
先把横坐标离散化,注意是线性离散的话初值不能是0因为有的坐标可以是0(因为这个所以WA0了)。
首先我们假设我们画的那一条直线在无限低的地方,这时候答案相当于相邻两个同种颜色的中间的最大点数。(注意不包括这种颜色)
怎么求?
把横坐标从小到大排序,维护l[i],r[i]分别表示距离i最近的相同颜色的点的编号。
直接维护比较麻烦,设一个last[i]表示i这种颜色最近一次出现的地方在哪个位置,然后用last维护l,r。
维护的同时维护答案,用树状数组和l,r维护一下区间和就好了。
当然,这是满状态,也就是直线在最下方的时候,然后我们将点按照纵坐标排序,逐渐向上移动,每一次将同一行的点从树状数组删掉,然后将l,r合并。同时维护答案,跟上面的一样,用已经合并了的l,r更新一下就好了。
最后还有一种情况就是枚举一下哪一种颜色不选,然后对ans取个max,注意要在删点之前,也是用树状数组维护。
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define fd(i,a,b) for(int i=a;i>=b;i--)
using namespace std;
const int N=1e5+5;
int n,k,ans;
struct point
{
int x,y,id,col;
}po[N];
int a[N],pos[N],val[N],last[N],Left[N],Right[N];
//int f[2][N][N];
inline int lowbit(int x)
{
return x&(-x);
}
inline void add(int x,int v)
{
while (x<=n+1)
{
val[x]+=v;
x+=lowbit(x);
}
}
inline int ask(int x)
{
int ret=0;
while (x>0)
{
ret+=val[x];
x-=lowbit(x);
}
return ret;
}
bool cmp1(point a,point b)
{
return a.x<b.x;
}
bool cmp2(point a,point b)
{
return a.y<b.y;
}
inline void solve()
{
memset(val,0,sizeof(val));
memset(last,0,sizeof(last));
sort(po+1,po+1+n,cmp1);
pos[n+1]=n+1;
fo(i,1,n)add(po[i].x,1);
fo(i,1,n)
{
int l=last[po[i].col];
Left[po[i].id]=l,Right[po[i].id]=n+1;
last[po[i].col]=po[i].id;
if (l)Right[l]=po[i].id;
if (pos[l]+1<=pos[po[i].id]-1)ans=max(ans,ask(pos[po[i].id]-1)-ask(pos[l]));
}
fo(i,1,k)if (pos[last[i]]+1<=n)ans=max(ans,ask(n+1)-ask(pos[last[i]]));
sort(po+1,po+1+n,cmp2);
int j=1;
fo(i,1,n)
{
while (j<=n&&po[i].y==po[j].y)add(po[j].x,-1),j++;
Left[Right[po[i].id]]=Left[po[i].id];
Right[Left[po[i].id]]=Right[po[i].id];
if (pos[Right[po[i].id]]-1>=pos[Left[po[i].id]]+1)
ans=max(ans,ask(pos[Right[po[i].id]]-1)-ask(pos[Left[po[i].id]]));
}
}
int main()
{
int cas=0;
scanf("%d",&cas);
while (cas--)
{
scanf("%d%d",&n,&k);
fo(i,1,n)
{
scanf("%d%d%d",&po[i].x,&po[i].y,&po[i].col);
a[i]=po[i].x;
po[i].id=i;
//fo(j,1,n)
//f[0][i][j]=abs(po[i].x-po[j].x),f[1][i][j]=abs(po[i].y-po[j].y);
}
sort(a+1,a+1+n);
int tot=0;
ans=0;
fo(i,1,n)
po[i].x=pos[i]=lower_bound(a+1,a+1+n,po[i].x)-a;
solve();
fo(i,1,n)po[i].y=-po[i].y;
solve();
printf("%d\n",ans);
}
}