Problem
Solution
只想到一个 O(n2) O ( n 2 ) 的做法,大概是这样。显然固定左端点,右端点扩展后矩形高度单调不升,那么就可以维护竖直和水平的两种链表,枚举左端点,然后不断扩展右端点,颜色数为k时就高度减小。
O(nlogn)
O
(
n
log
n
)
的做法比较巧妙,把矩形分为三类,一类是高度就是n的,另外两类就是上接和下接的。
考虑用树状数组按x轴维护点的个数。把x坐标离散化之后,用链表把x坐标相邻的同样颜色的点接起来,然后枚举即可。考虑上接的矩形,把点重新按y轴排序,从最小的开始枚举点,把y坐标小于等于它的全删除,那么矩形的左右就可以扩展到链表相接的左右端点。对于下下接的呢?直接把y坐标取负,再做同样的操作即可。
Code
#include <algorithm>
#include <cstring>
#include <cstdio>
#define rg register
#define lowbit(x) ((x)&(-(x)))
using namespace std;
typedef long long ll;
const int maxn=100010;
template <typename Tp> inline void getmin(Tp &x,Tp y){if(y<x) x=y;}
template <typename Tp> inline void getmax(Tp &x,Tp y){if(y>x) x=y;}
template <typename Tp> inline void read(Tp &x)
{
x=0;int f=0;char ch=getchar();
while(ch!='-'&&(ch<'0'||ch>'9')) ch=getchar();
if(ch=='-') f=1,ch=getchar();
while(ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
if(f) x=-x;
}
struct data{
int x,y,c,id;
bool operator < (const data &t)const{return x<t.x;}
}p[maxn];
int z,n,k,tot,ans,a[maxn],b[maxn],w[maxn],l[maxn],r[maxn],pre[maxn];
inline int cmp(data a,data b){return a.y<b.y;}
void add(int p,int v){for(;p<=n;p+=lowbit(p)) a[p]+=v;}
int query(int p,int res=0){for(;p;p-=lowbit(p)) res+=a[p];return res;}
void input()
{
read(n);read(k);ans=0;
for(rg int i=1;i<=n;i++)
{
read(p[i].x);read(p[i].y);read(p[i].c);p[i].id=i;
b[i]=p[i].x;
}
sort(b+1,b+n+1);
tot=unique(b+1,b+n+1)-b-1;
for(rg int i=1;i<=n;i++)
{
p[i].x=lower_bound(b+1,b+tot+1,p[i].x)-b;
w[i]=p[i].x;
}
}
inline void update(int l,int r){if(l<=r) getmax(ans,query(r)-query(l-1));}
void solve()
{
int x,y;
memset(a,0,sizeof(a));
memset(pre,0,sizeof(pre));
sort(p+1,p+n+1);w[0]=0;w[n+1]=n+1;
for(rg int i=1;i<=n;i++) add(p[i].x,1);
for(rg int i=1;i<=n;i++)
{
x=p[i].id;y=pre[p[i].c];
l[x]=y;r[x]=n+1;
if(y) r[y]=x;
update(w[y]+1,w[x]-1);
pre[p[i].c]=x;
}
for(rg int i=1;i<=k;i++) update(w[pre[i]]+1,n+1);
sort(p+1,p+n+1,cmp);
for(rg int i=1,j=1;i<=n;i++)
{
x=p[i].id;
while(j<=n&&p[j].y==p[i].y) add(p[j++].x,-1);
l[r[x]]=l[x];r[l[x]]=r[x];
update(w[l[x]]+1,w[r[x]]-1);
}
}
int main()
{
freopen("in.txt","r",stdin);
read(z);
while(z--)
{
input();
solve();
for(rg int i=1;i<=n;i++) p[i].y=-p[i].y;
solve();
printf("%d\n",ans);
}
return 0;
}