题意
有 N 个彩色糖果在平面上。小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果。求出最多能够拾起多少糖果,使得获得的糖果并不包含所有的颜色。
N ≤ 100000,K ≤ 100000,T ≤ 3
分析
只考虑在线段下方的情况。
首先很显然的思路就是枚举哪一种颜色不选。那么现在有两种情况:一种是一个点和在它下方的前驱和后继围成的矩形;一种是两个相邻点之间的那一部分矩形。
那么我们可以把所有点按照x坐标排序后用双向链表来维护每个点的前驱后继,然后按照纵坐标从大到小扫过去,同时用树状数组来维护矩形内的点数就好了。
代码
#include<iostream>
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=100005;
int n,m,c[N],l[N],r[N],ls[N],tmpl[N],tmpr[N],rank[N],w1,w[N];
struct data{int x,y,col;}a[N];
bool vis[N];
int read()
{
int x=0,f=1;char ch=getchar();
while (ch<'0'||ch>'9'){if(ch=='-')f=-1;ch=getchar();}
while (ch>='0'&&ch<='9'){x=x*10+ch-'0';ch=getchar();}
return x*f;
}
void ins(int x,int y)
{
while (x<=n) c[x]+=y,x+=x&(-x);
}
int find(int x)
{
int ans=0;
while (x) ans+=c[x],x-=x&(-x);
return ans;
}
bool cmpx(data a,data b)
{
return a.x<b.x||a.x==b.x&&a.y<b.y;
}
bool cmpy(int p,int q)
{
return a[p].y<a[q].y||a[p].y==a[q].y&&a[p].x<a[q].x;
}
int solve()
{
int ans=0;
sort(a+1,a+n+1,cmpx);
memset(ls,0,sizeof(ls));
for (int i=1;i<=n;i++) l[i]=!ls[a[i].col]?0:ls[a[i].col],ls[a[i].col]=i;
memset(ls,0,sizeof(ls));
for (int i=n;i>=1;i--) r[i]=!ls[a[i].col]?n+1:ls[a[i].col],ls[a[i].col]=i;
memset(c,0,sizeof(c));
for (int i=1;i<=n;i++) rank[i]=i,ins(a[i].x,1);
for (int i=1;i<=n;i++) ans=max(ans,find(a[i].x-1)-find(a[l[i]].x));
for (int i=1;i<=n;i++) ans=max(ans,find(a[r[i]].x-1)-find(a[i].x));
ans=max(ans,find(n)-find(a[n].x));
sort(rank+1,rank+n+1,cmpy);
for (int op=1,ed;op<=n;op=ed+1)
{
ed=op;int y=a[rank[op]].y;
while (ed<n&&a[rank[ed+1]].y==y) ed++;
for (int i=op;i<=ed;i++) ins(a[rank[i]].x,-1);
for (int i=op;i<=ed;i++)
if (a[l[rank[i]]].y==y) tmpl[i]=ls[a[rank[i]].col];
else tmpl[i]=l[rank[i]],ls[a[rank[i]].col]=tmpl[i];
for (int i=ed;i>=op;i--)
if (a[r[rank[i]]].y==y) tmpr[i]=ls[a[rank[i]].col];
else tmpr[i]=r[rank[i]],ls[a[rank[i]].col]=tmpr[i];
for (int i=op;i<=ed;i++) ans=max(ans,find(a[tmpr[i]].x-1)-find(a[tmpl[i]].x));
for (int i=op;i<=ed;i++)
{
int x=rank[i];
l[r[x]]=l[x];r[l[x]]=r[x];
}
}
return ans;
}
int main()
{
int T=read();
while (T--)
{
n=read();m=read();
w1=0;
memset(vis,0,sizeof(vis));
for (int i=1;i<=n;i++) a[i].x=read(),a[i].y=read(),a[i].col=read(),w[++w1]=a[i].x,vis[a[i].col]=1;
int woc=0;
for (int i=1;i<=m;i++) if (!vis[i]) woc=1;
if (woc)
{
printf("%d\n",n);
continue;
}
sort(w+1,w+w1+1);
w1=unique(w+1,w+w1+1)-w-1;
for (int i=1;i<=n;i++) a[i].x=lower_bound(w+1,w+w1+1,a[i].x)-w;
w1=0;
for (int i=1;i<=n;i++) w[++w1]=a[i].y;
sort(w+1,w+w1+1);
w1=unique(w+1,w+w1+1)-w-1;
for (int i=1;i<=n;i++) a[i].y=lower_bound(w+1,w+w1+1,a[i].y)-w;
int ans=0;
a[0].x=0;a[n+1].x=n+1;
ans=max(ans,solve());
for (int i=1;i<=n;i++) a[i].y=n-a[i].y+1;
ans=max(ans,solve());
printf("%d\n",ans);
}
return 0;
}