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环境搭建】

    springMVC作为spring的一个WEB组件,是一个MVC的思想,减少了WEB开发的难度,现介绍springMVC环境的搭建,具体的原理放在后面介绍.用过框架的朋友都知道要在WEB项目中使用一个 ...

  2. c中使用gets() 提示warning: this program uses gets(), which is unsafe.

    今天在C代码中使用gets()时提示“warning: this program uses gets(), which is unsafe.”,然后这个程序还能运行,无聊的我开始查阅资料,为啥gets ...

  3. rabbitmq trace 日志的使用以及其疑惑之处

    RabbitMQ 默认日志里只有类似客户端"accpet/close"等信息,对于有异常或者跟踪消息内部结构就比较麻烦了. 不过MQ有个rabbitmq_tracing插件,安装该 ...

  4. JAVA理解逻辑程序的书上全部重要的习题

    今天随便翻翻看以前学过JAVA理解逻辑程序的书上全部练习,为了一些刚学的学弟学妹,所以呢就把这些作为共享了. 希望对初学的学弟学妹有所帮助! 例子:升级“我行我素购物管理系统”,实现购物结算功能 代码 ...

  5. 使用mvc时,在视图view中使用强类型视图,在web.config文件中添加命名空间namespace的引用不起作用,解决方法

    这是view中的model代码: @model t_user_info 这是web.config配置文件只的代码: <namespaces> <add namespace=" ...

  6. Unable to extract 64-bitimage. Run Process Explorer from a writeable directory

    Unable to extract 64-bitimage. Run Process Explorer from a writeable directory When we run Process E ...

  7. Win7下共享WiFi热点方法

    管理员权限运行CMD netsh wlan set hostednetwork mode=allow ssid=Wifi名称 key=Wifi密码 netsh wlan start hostednet ...

  8. .net 配置文件设计工具 Configuration Section Designer

    Configuration Section Designer 简称 CSD 下载及英文介绍地址点击我 以下为简单使用说明 选择自己需要的版本安装好该设计插件之后重启vs 新建选择 在工具栏里选择想使用 ...

  9. Volley框架设置sessionid

    (偷懒,写简略点) 自定义一个Request类 public class MyRequest extends Request<JSONObject>   存储上一次连接的sessionid ...

  10. React Native知识4-Image组件

    一个用于显示多种不同类型图片的React组件,包括网络图片.静态资源.临时的本地图片.以及本地磁盘上的图片(如相册)等 一:属性 1:onLayout function 当元素挂载或者布局改变的时候调 ...