【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; }