Description
给出平面上n个点,每个点有颜色,求一条水平线段最多能包含多少个不包含所有颜色的点
n<=1e5
Solution
之所以写bzoj前缀是因为我是在bzoj上先过了这道题然后在OJ上卡常卡了一个下午
做法还是太naive
枚举一个不出现的颜色,就变成了许多限制
把这些限制按y坐标排序,在每个限制之前处理一下答案
那么我们就要处理出某个点下面和它在x坐标上相邻的两个点
这个东西我写了线段树,求一个矩形内的点数我写了主席树
其实这道题是卡常纪念_ (:з」∠) _
代码又臭又长不喜勿喷
Code
#include <cstdio>
#include <cstring>
#include <algorithm>
#define fo(i,a,b) for(int i=a;i<=b;i++)
#define rep(i,a) for(int i=last[a];i;i=ne[i])
#define min(a,b) (a<b)?a:b
#define max(a,b) (a>b)?a:b
using namespace std;
const int N=1e5+5;
int ty,n,k,ans,tot,cnt1,cnt2,num,sum,p,q,ss,now;
int last[N],ne[N],t[N];
int tr[N*50],le[N*50],ri[N*50],root[N];
bool bz[N];
inline int read() {
char ch;int fl=1;;
for(ch=getchar();ch<'0'||ch>'9';ch=getchar()) if (ch=='-') fl=-1;
int x=ch-'0';
for(ch=getchar();ch>='0'&&ch<='9';ch=getchar()) x=x*10+ch-'0';
return x*fl;
}
struct note{int v,id;}b[N];
inline bool cmp(note x,note y) {return x.v<y.v;}
struct point{int x,y,z;}a[N];
inline bool cmp1(point x,point y) {return x.z<y.z||x.z==y.z&&x.x<y.x;}
struct treee{int max,min;}tree[N*5];
inline void link(int x,int y) {
t[++num]=y;ne[num]=last[x];last[x]=num;
}
inline void add(int &v,int x,int l,int r,int y) {
if (v<now) {
v=++tot;
tr[v]=tr[x];
le[v]=le[x];
ri[v]=ri[x];
}
tr[v]++;
int m=(l+r)/2;
if (l==r) return;
if (y<=m) add(le[v],le[x],l,m,y);
else add(ri[v],ri[x],m+1,r,y);
}
inline void query(int v,int z,int l,int r,int x,int y) {
if (!v) return;
if ((l==x&&r==y)||(sum+tr[v]-tr[z]<=ss)) {
sum+=tr[v]-tr[z];
return;
}
int m=(l+r)/2;
if (y<=m) query(le[v],le[z],l,m,x,y);
else if (x>m) query(ri[v],ri[z],m+1,r,x,y);
else {
int pp=ss;ss=0;
query(le[v],le[z],l,m,x,m);
ss=pp;
query(ri[v],ri[z],m+1,r,m+1,y);
}
}
inline void get_sum(int rt,int x,int l,int r) {
if (l>r) return;
if (rt<x) return;
sum=0;ss=ans;
query(root[rt],root[x-1],1,cnt2,l,r);
ans=max(ans,sum);
}
inline void prepare() {
fo(i,1,n) root[i]=0;
fo(i,1,tot) tr[i]=le[i]=ri[i]=0;
tot=0;
fo(i,1,cnt1) {
now=tot+1;
rep(j,i)
add(root[i],root[i-1],1,cnt2,a[t[j]].y);
}
}
inline void build(int v,int l,int r) {
tree[v].max=0;tree[v].min=cnt2+1;
if (l==r) return;
int m=(l+r)/2;
build(v*2,l,m);build(v*2+1,m+1,r);
}
inline void modify(int v,int l,int r,int x) {
if (l==r) {
tree[v].max=max(tree[v].max,x);
tree[v].min=min(tree[v].min,x);
return;
}
int m=(l+r)/2;
if (x<=m) modify(v*2,l,m,x);
else modify(v*2+1,m+1,r,x);
tree[v].max=max(tree[v*2].max,tree[v*2+1].max);
tree[v].min=min(tree[v*2].min,tree[v*2+1].min);
}
inline void revoke(int v,int l,int r,int x) {
if (l==r) {
tree[v].max=0;
tree[v].min=cnt2+1;
return;
}
int m=(l+r)/2;
if (x<=m) revoke(v*2,l,m,x);
else revoke(v*2+1,m+1,r,x);
tree[v].max=max(tree[v*2].max,tree[v*2+1].max);
tree[v].min=min(tree[v*2].min,tree[v*2+1].min);
}
inline void get_max(int v,int l,int r,int x,int y) {
if (x>y) return;
if (tree[v].max==0) return;
if (l==x&&r==y) {p=max(p,tree[v].max);return;}
int m=(l+r)/2;
if (y<=m) get_max(v*2,l,m,x,y);
else if (x>m) get_max(v*2+1,m+1,r,x,y);
else {
get_max(v*2+1,m+1,r,m+1,y);
if (p==0) get_max(v*2,l,m,x,m);
}
}
inline void get_min(int v,int l,int r,int x,int y) {
if (x>y) return;
if (tree[v].min==cnt2+1) return;
if (l==x&&r==y) {q=min(q,tree[v].min);return;}
int m=(l+r)/2;
if (y<=m) get_min(v*2,l,m,x,y);
else if (x>m) get_min(v*2+1,m+1,r,x,y);
else {
get_min(v*2,l,m,x,m);
if (q==cnt2+1) get_min(v*2+1,m+1,r,m+1,y);
}
}
inline void solve(bool flag) {
build(1,1,cnt2);
for(int l=1,r=0;l<=n;l=r+1) {
while (a[r+1].z==a[l].z) r++;
for(int left=l,right=left-1;left<=r;left=right+1) {
while (a[right+1].x==a[left].x) right++;
fo(i,left,right) {
p=0;get_max(1,1,cnt2,1,a[i].y);
q=cnt2+1;get_min(1,1,cnt2,a[i].y+1,cnt2);
if (flag) get_sum(cnt1,a[i].x+1,p+1,q-1);
else get_sum(a[i].x-1,1,p+1,q-1);
}
fo(i,left,right) modify(1,1,cnt2,a[i].y);
}
for(int x=1;x<=cnt2;x=q+1) {
q=cnt2+1;
get_min(1,1,cnt2,x,cnt2);
get_sum(cnt1,1,x,q-1);
}
fo(i,l,r) revoke(1,1,cnt2,a[i].y);
}
}
int main() {
for(ty=read();ty;ty--) {
n=read();k=read();ans=0;
memset(bz,0,sizeof(bz));int cnt=0;
fo(i,1,n) {
a[i].x=read();a[i].y=read();a[i].z=read();
swap(a[i].x,a[i].y);
if (!bz[a[i].z]) bz[a[i].z]=1,cnt++;
}
if (cnt<k) {
printf("%d\n",n);
continue;
}
fo(i,1,n) b[i].v=a[i].x,b[i].id=i;
sort(b+1,b+n+1,cmp);cnt1=0;
fo(i,1,n) {
if (i==1||b[i].v!=b[i-1].v) cnt1++;
a[b[i].id].x=cnt1;
}
fo(i,1,n) b[i].v=a[i].y,b[i].id=i;
sort(b+1,b+n+1,cmp);cnt2=0;
fo(i,1,n) {
if (i==1||b[i].v!=b[i-1].v) cnt2++;
a[b[i].id].y=cnt2;
}
memset(last,0,sizeof(last));num=0;
fo(i,1,n) link(a[i].x,i);
prepare();
sort(a+1,a+n+1,cmp1);
solve(0);
fo(i,1,n/2) swap(a[i],a[n-i+1]);
solve(1);
printf("%d\n",ans);
}
}