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. PowerDesigner15在win7-64位系统下对MySQL 进行反向工程以及建立物理模型产生SQL语句步骤图文傻瓜式详解

    1.安装PowerDesigner15.MySQL5.不详细讲解了.网上一大把.请各位亲参考去. 2.安MyODBC-standard-3.51.0.7-win.msi.mysql-connector ...

  2. PHP的变量和常量

  3. mysql 5.7.15单机主从快速搭建并配置复制表到不同库

    一直以来因为线上系统盘中风控计算过于消耗资源,导致服务器负载太高,时常影响盘中交易的稳定性,最近决定了将风控拆分到独立的库进行计算,并进行回填操作. 总体来说,是将部分风控计算相关的表同步到备库,但是 ...

  4. UML常用图

    序列图 活动图

  5. 使用gulp+browser-sync搭建前端项目自动化以及自动刷新

    前段时间使用了gulp+browser-sync才发现这个东西真的很好用. 准备工作:(1).安装nodejs.gulp是基于nodejs使用的,所以先安装nodejs,https://nodejs. ...

  6. Oracle常用SQL查询

    一.ORACLE的启动和关闭 1.在单机环境下要想启动或关闭oracle系统必须首先切换到oracle用户,如下: su - oracle a.启动Oracle系统 oracle>svrmgrl ...

  7. chrome 调试 SASS

    第一步: 执行sass预编译命令 先来我的项目文件夹结构: ->进入sass /css文件下->打开cmd命令 ->输入sass --watch --scss  test.scss: ...

  8. SQLBackupAndFTP The server principal "NT AUTHORITY\SYSTEM" is not able to access the database "xxxx"

    Windows server 2012中使用SQLBackupAndFTP备份数据库时遇到一个错误: ERROR: The server principal "NT AUTHORITY\SY ...

  9. SQL SERVER中的OLEDB等待事件

    OLEDB等待事件介绍 OLEDB等待类型是SQL SERVER 数据库中最常见的几种等待类型之一.它意味着某个会话(SPID)通过SQL Server Native Client OLEDB Pro ...

  10. Could not obtain information about Windows NT group/user 'xxxx\xxxx', error code 0x5

    案例描述 昨晚踢球回来,接到电话说一个系统的几个比较重要作业出错,导致系统数据有些问题.让我赶紧检查看看.检查作业日志时发现,作业报如下错误(关键信息用xxx替换) The job failed.  ...