Description

有 \(N\) 个彩色糖果在平面上。小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果。求出最多能够拾起多少糖果,使得获得的糖果并不包含所有的颜色。

Input

包含多组测试数据,第一行输入一个正整数 \(T\) 表示测试数据组数。

接下来 $T$ 组测试数据,对于每组测试数据,第一行输入两个正整数 $N$、$K$,分别表示点数和颜色数。
接下来 $N$ 行,每行描述一个点,前两个数 $x, y(|x|, |y| \leqslant 2^{30} - 1)$ 描述点的位置,最后一个数 $z$ $(1 \leqslant z \leqslant k)$ 描述点的颜色。
对于 $100\%$ 的数据,$N \leqslant 100000$ , $K \leqslant 100000$ , $T \leqslant 3$

Output

对于每组数据在一行内输出一个非负整数 $ans$,表示答案

  这道题要我们求一条线段上面的所有点或者是下面的所有点的个数(在满足题意的1情况下)。这可以转化为求矩形内部点的个数。

  那么,一共有三种矩形。每个矩形肯定会有左右边界(因为是线段),那么三种矩形分别是只有上边界(情况1),只有下边界(情况2)和上下边界都没有(情况3)。

  然后,情况1和情况2具有对称性。我们只需要把每个点的纵坐标取个反就可以由情况1的算法退出情况2了。因此,我们无需考虑情况2。

  首先,我们来考虑情况1的矩形最大可以到哪里。显然,这个矩形的左、右、下边界都受到了同一种颜色的点的制约(或者已经到了所有点之外),因而不能继续拓展。所以,我们可以考虑枚举下边界那个点$x$,那么左边界就是$x$左边的点中第一个纵坐标大于他的。右边界同理。

  这种操作是经典的平衡树操作。但同时也可以使用树状数组加挂链来解决。先把所有点按横坐标排好序,相同颜色的点挂好双向链表,然后再按纵坐标从排序,自底向上扫过去,每次从链表中删去一个点即可。

  这样做还有一个好处,就是同时可以对横坐标建一个树状数组来维护区域内点的个数了。只需一开始把所有点都加进去,然后拿出一个点作下边界,就把纵坐标等于这个点纵坐标的所有点从树状数组中删去即可。

  最后考虑情况3。由于上下边界都没有,这实际上转化成了一个序列问题。我们可以按横坐标排好序,从前往后扫一边,每扫到一个点就用上一个相同颜色的点与这个点之间点的个数更新一下答案。最后再用最后的点到空区域之间的点更新一下答案即可。

  下面贴代码(我写的好像比较丑):

#include<iostream>
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<cmath>
#define File(s) freopen(s".in","r",stdin),freopen(s".out","w",stdout)
#define maxn 100010 using namespace std;
typedef long long llg; struct data{
int x,y,b,z;
}s[maxn],ss[maxn];
int T,n,K,c[maxn],lt[maxn];
int dx[maxn],lx,dy[maxn],ly;
int pr[maxn],ne[maxn],ans;
int w[maxn]; int getint(){
int w=0;bool q=0;
char c=getchar();
while((c>'9'||c<'0')&&c!='-') c=getchar();
if(c=='-') c=getchar(),q=1;
while(c>='0'&&c<='9') w=w*10+c-'0',c=getchar();
return q?-w:w;
} bool cmpx(data a,data b){if(a.x!=b.x)return a.x<b.x;return a.y<b.y;}
bool cmpy(data a,data b){if(a.y!=b.y)return a.y<b.y;return a.x<b.x;}
void add(int x,int y){while(x<=lx) c[x]+=y,x+=x&(-x);}
int sum(int x){
int t=0;
while(x) t+=c[x],x-=x&(-x);
return t;
} void solve(){
sort(s+1,s+n+1,cmpx); ss[n+1].x=lx+1;
for(int i=1;i<=K;i++) lt[i]=0;
for(int i=1;i<=n;i++){
add(s[i].x,1); pr[s[i].b]=lt[s[i].z];
if(lt[s[i].z]) ne[lt[s[i].z]]=s[i].b;
lt[s[i].z]=s[i].b;
}
for(int i=1;i<=K;i++) ne[lt[i]]=n+1;
sort(s+1,s+n+1,cmpy);
for(int k=1,j;k<=n;k=j){
j=k+1; add(s[k].x,-1);
while(j<=n && s[j].y==s[k].y) add(s[j].x,-1),j++;
for(int i=k;i<j;i++){
int l=pr[s[i].b],r=ne[s[i].b];
ans=max(ans,sum(ss[r].x-1)-sum(ss[l].x));
ne[l]=r; pr[r]=l; pr[s[i].b]=ne[s[i].b]=0;
}
}
} int main(){
File("a");
T=getint();
while(T--){
n=getint(); K=getint(); lx=ly=ans=0;
for(int i=1;i<=n;i++){
dx[++lx]=s[i].x=getint();
dy[++ly]=s[i].y=getint();
s[i].b=i,s[i].z=getint();
}
sort(dx+1,dx+lx+1); lx=unique(dx+1,dx+lx+1)-dx-1;
sort(dy+1,dy+ly+1); ly=unique(dy+1,dy+ly+1)-dy-1;
for(int i=1;i<=n;i++){
s[i].x=lower_bound(dx+1,dx+lx+1,s[i].x)-dx;
s[i].y=lower_bound(dy+1,dy+ly+1,s[i].y)-dy;
}
for(int i=1;i<=n;i++) ss[i]=s[i];
solve(); for(int i=1;i<=n;i++) s[i].y=ly+1-s[i].y; solve();
sort(s+1,s+n+1,cmpx);
for(int i=1;i<=K;i++) lt[i]=0;
for(int i=1;i<=n;i++){
ans=max(ans,w[s[i].x-1]-w[lt[s[i].z]]);
w[s[i].x+1]=++w[s[i].x]; lt[s[i].z]=s[i].x;
}
for(int i=1;i<=K;i++) ans=max(ans,n-w[lt[i]]);
for(int i=1;i<=lx;i++) w[i]=0;
printf("%d\n",ans);
}
return 0;
}

  

BZOJ 4548 小奇的糖果的更多相关文章

  1. 【BZOJ-4548&3658】小奇的糖果&Jabberwocky 双向链表 + 树状数组

    4548: 小奇的糖果 Time Limit: 10 Sec  Memory Limit: 256 MBSubmit: 103  Solved: 47[Submit][Status][Discuss] ...

  2. 【BZOJ4548】小奇的糖果 set(链表)+树状数组

    [BZOJ4548]小奇的糖果 Description 有 N 个彩色糖果在平面上.小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果.求出最多能够拾起多少糖果,使得获得的糖果并不包含所有的 ...

  3. 【BZOJ4548】小奇的糖果

    →原题传送门←(by Hzwer) 「题目背景」 小奇不小心让糖果散落到了地上,它对着满地的彩色糖果胡思乱想. 「问题描述」 有 N 个彩色糖果在平面上.小奇想在平面上取一条水平的线段,并拾起它上方或 ...

  4. 【题解】BZOJ4548 小奇的糖果(树状数组)

    [题解]BZOJ4548 小奇的糖果(树状数组) 说在前面:我有个同学叫小奇,他有一个朋友叫达达,达达特爱地理和旅游,初中经常AK地理,好怀恋和他已经达达一起到当时初中附近许多楼盘的顶楼逛的时光... ...

  5. 小奇的糖果(candy)

    [题目背景]小奇不小心让糖果散落到了地上,它对着满地的彩色糖果胡思乱想.[问题描述]有 N 个彩色糖果在平面上. 小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果.求出最多能够拾起多少糖果 ...

  6. bzoj 4547 小奇的集合

    Description 有一个大小为n的可重集S,小奇每次操作可以加入一个数a+b(a,b均属于S),求k次操作后它可获得的S的和的最大 值.(数据保证这个值为非负数) Input 第一行有两个整数n ...

  7. BZOJ4548 小奇的糖果

    本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...

  8. Bzoj4548 小奇的糖果(链表+树状数组)

    题面 Bzoj 题解 很显然,我们只需要考虑单独取线段上方的情况,对于下方的把坐标取反再做一遍即可(因为我们只关心最终的答案) 建立树状数组维护一个横坐标区间内有多少个点,维护双向链表实现查询一个点左 ...

  9. 【题解】 BZOJ4548 小奇的糖果

    本文同步在学弟ZCDHJ的个人博客发布,审核需要一段时间. 传送门 考虑题目中获得的糖果并不包含所有的颜色这句话,发现相当于我们可以直接选取某一个颜色强制不能选(这样子一定最优). 然后就可以考虑分开 ...

随机推荐

  1. Linux Cmd Tool 系列之—script & scriptreplay

    Intro Sometime we want to record cmd and outputs in the interactive shell sessions. However history ...

  2. 关于tomcat文件下载配置

    前言 tomcat文件下载 关闭tomcat目录列表浏览功能 Tomcat 不能下载带中文文件名的附件的方法 在Java Web项目中文件下载是一个很常见的功能,最近在做项目中发现可以通过tomcat ...

  3. POI导入导出

    一.使用POI导出Execl表格 需要的jar包 package cn.yxj.poi; import java.io.FileOutputStream; import java.util.Date; ...

  4. 哈哈:sqlserver2008附加数据库时操作系统错误5(拒绝访问)错误5012的解决办法

    老师说:无论干什么,出错了,先大笑三声.如果人多了,在心里也要大笑三声.哈哈哈!!! 刚刚重装系统完后,然后想学习.自己去安装sqlserver2008数据库,完之后想附加之前的数据库.可是当我一点确 ...

  5. [转载]Javascript异步编程的4种方法

    NodeJs的最大特性就是"异步" 目前在NodeJs里实现异步的方法中,使用“回调”是最常见的. 其实还有其他4种实现异步的方法: 在此以做记录 --- http://www.r ...

  6. angular源码分析:angular中入境检察官$sce

    一.ng-bing-html指令问题 需求:我需要将一个变量$scope.x = '<a href="http://www.cnblogs.com/web2-developer/&qu ...

  7. Material Design 概念,环境和基本属性

    Material Design 概念,环境和基本属性 Material Design是随Android 5.0推出的一种设计概念, 涉及到了跨平台和设备的视觉,动态,交互设计等方面.   设计概念 M ...

  8. iOS 直播-网速监控

    iOS 直播-网速监控 CXNetworkSpeed.h // // CXNetworkSpeed.h // CXNetworkSpeedDemo // // Created by xubaoaich ...

  9. 敏捷开发与jira

    项目背景 项目是基于一套公司自主研发的平台做企业信息化的项目管理业务,经过两个里程碑的交付,已经在客户现场使用,每次版本都能按期交付,延迟较少,客户满意度也高. 项目开发过程采用的敏捷的方法,用类Sc ...

  10. Windows 双网卡指定网络出口

    主要命令: ipconfig route ping tracert     指定外网路由通过本地以太网连接出去 route add -p 0.0.0.0 mask 0.0.0.0 192.168.10 ...