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. spring入门(六)【springMVC中各数据源配置】

    在使用spring进行javaWeb开发的过程中,需要和数据库进行数据交换,为此要经常获取数据库连接,使用JDBC的方式获取数据库连接,使用完毕之后再释放连接,这种过程对系统资源的消耗无疑是很大的,这 ...

  2. Could not publish server configuration for Tomcat v6.0 Server at localhost.

    经常在使用tomcat服务器的时候 总会发生一些莫名其妙的错误. 就像下面这个错误: 在配置文件中存在多个/MyWeb的配置,导致不能发布服务. 错误信息: Could not publish ser ...

  3. redhat6.4安装MySQL-server-5.5.28-1.linux2.6.x86_64.rpm

    首先下载下面三个文件: MySQL-server-5.5.28-1.linux2.6.x86_64.rpm MySQL-client-5.5.28-1.linux2.6.x86_64.rpm MySQ ...

  4. iOS 封装添加按钮的方法

    添加按钮 #pragma mark 添加按钮 - (void)addButtonWithImage:(NSString *)image highImage:(NSString *)highImage ...

  5. iOS 杂笔-25(不要用copy修饰NSMutableString)

    iOS 杂笔-25(不要用copy修饰NSMutableString) 首先对题目进行简单的解释,我所说的不要用copy修饰NSMutableString不是说完全不可以用.但是要清楚一点,既然使用N ...

  6. Android 面试题汇总

    面试题基础储备 1.Activity相关 a.Activity的特点 1.可见  2.可交互 他之所以可交互,是因为他同时实现了Window.Callback和KeyEvent.Callback, 可 ...

  7. Windows Universal 应用 – Tip Calculator

    声明 以下内容取材于 Bob Tabor 的课程<Windows Phone 8.1 Development for Absolute Beginners>,链接地址为:http://ww ...

  8. 通过Ajax使用FormData对象无刷新上传文件

    写在前面:本文说的这个方案有浏览器兼容性问题:所有主流浏览器的较新版本已经支持这个对象了,比如Chrome 7+.Firefox 4+.IE 10+.Opera 12+.Safari 5+,对兼容性比 ...

  9. Linux命令学习总结: file命令

    命令简介: 该命令用来识别文件类型,也可用来辨别一些文件的编码格式.它是通过查看文件的头部信息来获取文件类型,而不是像Windows通过扩展名来确定文件类型的. 执行权限 :All User 指令所在 ...

  10. JS/JQuery针对不同类型元素的操作(radio、select、checkbox)

    一.select下拉框 I:javascript方法 1:获取选中的值 F1:   var  myselect=document.getElementById("test");或者 ...