BZOJ4548 小奇的糖果
Link
把\(x\)离散化,\(y\)降序排序,每种颜色开一个set。
因为我们需要不包含所有颜色,所以强制某种颜色不被包含即可。
对于某一个点,如果选出的矩形以其为下边界(不取到),左边界就是前驱的横坐标,右边界就是后继的横坐标(都取不到)。
前驱后继可以使用平衡树set或链表维护,计算一个范围内的点数可以使用树状数组维护。
然后我们从上面往下面枚举每一个\(y\)坐标,对于这个\(y\)坐标的每一个点计算答案,然后把它加入\(set\)和树状数组。
最后再枚举没有下边界的矩形。
做完之后再从下往上做一遍即可。
#include<bits/stdc++.h>
using namespace std;
const int N=100007;
set<int>s[N];
struct node{int x,y,col;}a[N];
int n,m,b[N],t[N],ans;
int operator<(node a,node b){return a.y<b.y;}
int read(){int x;scanf("%d",&x);return x;}
int max(int a,int b){return a>b? a:b;}
void add(int p){for(;p<=n;p+=p&-p) ++t[p];}
int query(int p){int sum=0;for(;p;p-=p&-p) sum+=t[p];return sum;}
void solve()
{
int i,j,k,c;
set<int>::iterator it;
memset(t,0,sizeof t);
for(i=1;i<=m;++i) s[i].clear(),s[i].insert(0),s[i].insert(n+1);
for(i=j=1;i<=n;i=j)
{
while(j<=n&&a[j].y==a[i].y) ++j;
for(k=i;k<j;++k) c=a[k].col,ans=max(ans,query(*s[c].lower_bound(a[k].x)-1)-query(*--s[c].upper_bound(a[k].x)));
for(k=i;k<j;++k) add(a[k].x),s[a[k].col].insert(a[k].x);
}
for(i=1;i<=m;++i) for(it=s[i].begin();(*it)^(n+1);) j=*it,ans=max(ans,query(*++it-1)-query(j));
}
int main()
{
for(int i,T=read();T;--T)
{
n=read(),m=read(),ans=0;
for(i=1;i<=n;++i) b[i]=a[i].x=read(),a[i].y=read(),a[i].col=read();
sort(a+1,a+n+1),sort(b+1,b+n+1);
for(i=1;i<=n;++i) a[i].x=lower_bound(b+1,b+n+1,a[i].x)-b;
solve();
for(i=1;i<=n>>1;++i) swap(a[i],a[n-i+1]);
solve(),printf("%d\n",ans);
}
}