BZOJ 4548 小奇的糖果
Description
有 \(N\) 个彩色糖果在平面上。小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果。求出最多能够拾起多少糖果,使得获得的糖果并不包含所有的颜色。
Input
包含多组测试数据,第一行输入一个正整数 \(T\) 表示测试数据组数。
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 小奇的糖果的更多相关文章
- 【BZOJ-4548&3658】小奇的糖果&Jabberwocky 双向链表 + 树状数组
4548: 小奇的糖果 Time Limit: 10 Sec Memory Limit: 256 MBSubmit: 103 Solved: 47[Submit][Status][Discuss] ...
- 【BZOJ4548】小奇的糖果 set(链表)+树状数组
[BZOJ4548]小奇的糖果 Description 有 N 个彩色糖果在平面上.小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果.求出最多能够拾起多少糖果,使得获得的糖果并不包含所有的 ...
- 【BZOJ4548】小奇的糖果
→原题传送门←(by Hzwer) 「题目背景」 小奇不小心让糖果散落到了地上,它对着满地的彩色糖果胡思乱想. 「问题描述」 有 N 个彩色糖果在平面上.小奇想在平面上取一条水平的线段,并拾起它上方或 ...
- 【题解】BZOJ4548 小奇的糖果(树状数组)
[题解]BZOJ4548 小奇的糖果(树状数组) 说在前面:我有个同学叫小奇,他有一个朋友叫达达,达达特爱地理和旅游,初中经常AK地理,好怀恋和他已经达达一起到当时初中附近许多楼盘的顶楼逛的时光... ...
- 小奇的糖果(candy)
[题目背景]小奇不小心让糖果散落到了地上,它对着满地的彩色糖果胡思乱想.[问题描述]有 N 个彩色糖果在平面上. 小奇想在平面上取一条水平的线段,并拾起它上方或下方的所有糖果.求出最多能够拾起多少糖果 ...
- bzoj 4547 小奇的集合
Description 有一个大小为n的可重集S,小奇每次操作可以加入一个数a+b(a,b均属于S),求k次操作后它可获得的S的和的最大 值.(数据保证这个值为非负数) Input 第一行有两个整数n ...
- BZOJ4548 小奇的糖果
本文版权归ljh2000和博客园共有,欢迎转载,但须保留此声明,并给出原文链接,谢谢合作. 本文作者:ljh2000作者博客:http://www.cnblogs.com/ljh2000-jump/转 ...
- Bzoj4548 小奇的糖果(链表+树状数组)
题面 Bzoj 题解 很显然,我们只需要考虑单独取线段上方的情况,对于下方的把坐标取反再做一遍即可(因为我们只关心最终的答案) 建立树状数组维护一个横坐标区间内有多少个点,维护双向链表实现查询一个点左 ...
- 【题解】 BZOJ4548 小奇的糖果
本文同步在学弟ZCDHJ的个人博客发布,审核需要一段时间. 传送门 考虑题目中获得的糖果并不包含所有的颜色这句话,发现相当于我们可以直接选取某一个颜色强制不能选(这样子一定最优). 然后就可以考虑分开 ...
随机推荐
- 学习.NET是因为热爱 or 兴趣 or 挣钱?
看到最近园子里掀起了“.NET快不行了”.“.NET工资太低了”.“转行做XX”等一系列之风,不由得想说点什么,我只是基于自己的观点,你认同或者不认同,我就是这样认为,无所谓对与错,写文章就是为了交流 ...
- 浅谈tornado项目应用设计
一.预备知识 最近开始尝试做一些tornado商城项目,在开始之前需要引入一些项目设计知识,如接口,抽象方法抽象类,组合,程序设计原则等,个人理解项目的合理设计可增加其灵活性,降低数据之间的耦合性,提 ...
- jquery右下角自动弹出关闭层
效果体验:http://keleyi.com/keleyi/phtml/jqtexiao/36.htm 右下角弹出层后,会在一定时间后自动隐藏.第一版本:http://www.cnblogs.com/ ...
- Linux系统NFS网络文件系统
Linux系统NFS网络文件系统 NFS(network file system)网络文件系统,就是通过网络让不同的主机系统之间可以共享文件或目录,此种方法NFS客户端使用挂载的方式让共享文件或目录到 ...
- 在 CentOS7 上部署 zookeeper 服务
在 CentOS7 上部署 zookeeper 服务 1 用 SecureCRT 或 XShell 等 Linux 客户端工具连接至 CentOS7 服务器: 2 进入到 /usr/local/too ...
- 在 CentOS7 上安装 Tomcat9
在 CentOS7 上安装 Tomcat9 1 通过 SecureCRT 连接到阿里云 CentOS7 服务器: 2 进入到目录 /usr/local/ 中: cd /usr/local/ 3 创建目 ...
- 解决idea中执行maven命令失败的问题
1.问题描述 如上图所示,在使用idea 里的maven命令执行项目打包时,有时候会报如下一个错误. -Dmaven.multiModuleProjectDirectory system proper ...
- mac系统及xcode使用的SVN客户端安装升级
当前的SVN版本已经升级到1.8.x了,但mac系统自带的以及xcode使用的SVN客户端版本没有跟着升级,还是1.6.x的版本.为了解决隐藏目录.svn只在根目录下存在的情况,至少要升级到1.7.x ...
- 深入解析Windows操作系统笔记——CH3系统机制
3.系统机制 微软提供了一些基本组件让内核模式的组件使用: 1.陷阱分发,包括终端,延迟的过程调用(DPC),异步过程调用(APC),异常分发以及系统服务分发 2.执行体对象管理器 3.同步,包括自旋 ...
- SQL Update:使用一个表的数据更新另一张表
表结构 功能 用表B的数据(mc列)更新表A的mc列 SQL Server update A SET A.mc = b.mc FROM A ,B WHERE A.bmbh = B.bmbh and A ...