【BZOJ4548】小奇的糖果
【BZOJ4548】小奇的糖果
传送门
Solution
如果你觉得这道题目比较奇怪,请认真审题
线段不是直线
我们可以强制一种颜色不选,因为多种颜色不选一定不会比一种颜色不选优,此时考虑选取的颜色情况:
- 选取两个相邻颜色中间的颜色
- 将最上面的颜色删除,选取他下面两个相邻的颜色中间的。
注意这个可以排序+树状数组维护。
Code
#include<stdio.h>
#include<stdlib.h>
#include<string.h>
#include<math.h>
#include<algorithm>
#include<queue>
#include<iostream>
using namespace std;
inline int gi(){
int sum=0,f=1;char ch=getchar();
while(ch>'9' || ch<'0'){if(ch=='-')f=-1;ch=getchar();}
while(ch>='0' && ch<='9'){sum=(sum<<3)+(sum<<1)+ch-'0';ch=getchar();}
return f*sum;
}
int ans,n,K,c[500010],x[500010],l[500010],r[500010],last[500010],b[500010];
struct node{
int id,x,y,z;
}p[500010];
int lowbit(int x){
return x&-x;
}
void add(int x,int d){
for(;x<=n+1;x+=lowbit(x))c[x]+=d;
}
int query(int x){
int res=0;
for(;x>0;x-=lowbit(x))res+=c[x];
return res;
}
bool cmp1(node a,node b){
return a.x<b.x;
}
bool cmp2(node a,node b){
return a.y<b.y;
}
void update(int l,int r){
if(l>r)return;
ans=max(ans,query(r)-query(l-1));
}
void solve(){
x[0]=0;x[n+1]=n+1;
memset(c,0,sizeof(c));memset(last,0,sizeof(last));
sort(p+1,p+n+1,cmp1);
for(int i=1;i<=n;i++)add(p[i].x,1);
for(int i=1;i<=n;i++){
int t=p[i].id,L=last[p[i].z];
l[t]=L;r[t]=n+1;
if(L)r[L]=t;update(x[L]+1,x[t]-1);
last[p[i].z]=t;
}
for(int i=1;i<=K;i++)update(x[last[i]]+1,n+1);
sort(p+1,p+n+1,cmp2);
for(int i=1,j=1;i<=n;i++){
int t=p[i].id;
while(j<=n && p[i].y==p[j].y)add(p[j].x,-1),j++;
l[r[t]]=l[t];r[l[t]]=r[t];
update(x[l[t]]+1,x[r[t]]-1);
}
}
int main(){
#ifndef ONLINE_JUDGE
freopen("in.in","r",stdin);
freopen("out.out","w",stdout);
#endif
int T=gi();
while(T--){
ans=0;
n=gi();K=gi();
for(int i=1;i<=n;i++){
p[i].x=gi();p[i].y=gi();p[i].z=gi();
p[i].id=i;
}
for(int i=1;i<=n;i++)b[i]=p[i].x;
sort(&b[1],&b[n+1]);
for(int i=1;i<=n;i++){
p[i].x=lower_bound(b+1,b+n+1,p[i].x)-b;
x[i]=p[i].x;
}
solve();
for(int i=1;i<=n;i++)p[i].y=-p[i].y;
solve();
printf("%d\n",ans);
}
return 0;
}