【BZOJ4548】小奇的糖果

Description

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

Input

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

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

Output

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

Sample Input

1
10 3
1 2 3
2 1 1
2 4 2
3 5 3
4 4 2
5 1 2
6 3 1
6 7 1
7 2 3
9 4 2

Sample Output

5

题解:一开始想的是:不包含所有颜色=有一种颜色不出现,所以我们枚举不出现哪个颜色即可。而一个颜色出现的位置有很多,我们相当于用这些点将平面分成若干个部分,然后在每个部分里都统计一下点的个数即可。不过该怎么分呢?蒟蒻就卡到这了,然而看大爷的博客发现可以分治。。。感觉神的不行。

所以还是来看一种简单的方法吧!我们先只考虑向下的情况。我们将所有点按y值从小到大排序,然后从下往上一层一层的加入到平面中(一层一层指的是y值相同的点要同时加入)。在加入一个点之前,我们先用set找到与它颜色相同的,已经加入到平面中的点的,x值的前驱和后继,然后用树状数组统计一下前驱到后继之间这部分的点数,然后再将这个点加进去。最后可能有没被统计过得部分,再查询一遍所有点即可。

向上的情况呢?反过来做一遍即可。

PS:如果你将一个一个加点改成一个一个删点,那就可以用链表来维护前驱后继了~

#include <cstdio>
#include <cstring>
#include <iostream>
#include <algorithm>
#include <set>
#include <utility>
#define mp(A,B) make_pair(A,B)
using namespace std;
const int maxn=100010;
typedef pair<int,int> pii;
int n,m,nm,cnt,ans;
struct point
{
int x,y,col;
}p[maxn];
struct node
{
int val,org;
}num[maxn];
int v[maxn],vis[maxn],s[maxn],st[maxn];
set<int> S[maxn];
set<int>::iterator it;
inline int rd()
{
int ret=0,f=1; char gc=getchar();
while(gc<'0'||gc>'9') {if(gc=='-')f=-f; gc=getchar();}
while(gc>='0'&&gc<='9') ret=ret*10+gc-'0',gc=getchar();
return ret*f;
}
bool cmpv(const node &a,const node &b)
{
return a.val<b.val;
}
bool cmpy(const point &a,const point &b)
{
return a.y<b.y;
}
inline void updata(int x)
{
for(int i=x;i<=nm;i+=i&-i) s[i]++;
}
inline int query(int x)
{
int i,ret=0;
for(i=x;i;i-=i&-i) ret+=s[i];
return ret;
}
inline void insert(int x)
{
S[p[x].col].insert(p[x].x),updata(p[x].x),cnt+=(!vis[p[x].col]),vis[p[x].col]=1;
}
inline void calc(int x)
{
int a,b;
it=S[p[x].col].lower_bound(p[x].x),b=(it==S[p[x].col].end()?nm+1:(*it));
it=S[p[x].col].upper_bound(p[x].x),a=(it==S[p[x].col].begin()?0:(*(--it)));
ans=max(ans,query(b-1)-query(a));
}
inline void init()
{
memset(vis,0,sizeof(vis)),memset(s,0,sizeof(s)),cnt=0;
for(int i=1;i<=m;i++) S[i].clear();
}
void work()
{
n=rd(),m=rd(),nm=ans=0;
int i,j,a,b;
for(i=1;i<=n;i++) num[i].val=rd(),num[i].org=i,p[i].y=rd(),p[i].col=rd();
sort(num+1,num+n+1,cmpv);
for(i=1;i<=n;i++)
{
if(i==1||num[i].val>num[i-1].val) nm++;
p[num[i].org].x=nm;
}
p[0].x=1,p[n+1].x=n;
sort(p+1,p+n+1,cmpy);
init();
for(i=1;i<=n;i++)
{
st[st[0]=1]=i;
while(i<n&&p[i+1].y==p[i].y) st[++st[0]]=++i;
for(j=1;j<=st[0];j++) calc(st[j]);
for(j=1;j<=st[0];j++) insert(st[j]);
if(cnt<m) ans=max(ans,i);
}
for(i=1;i<=n;i++)
{
it=S[p[i].col].upper_bound(p[i].x),b=(it==S[p[i].col].end()?nm+1:(*it));
it=S[p[i].col].lower_bound(p[i].x),a=(it==S[p[i].col].begin()?0:(*(--it)));
ans=max(ans,query(b-1)-query(p[i].x)),ans=max(ans,query(p[i].x-1)-query(a));
}
init();
for(i=n;i;i--)
{
st[st[0]=1]=i;
while(i>1&&p[i-1].y==p[i].y) st[++st[0]]=--i;
for(j=1;j<=st[0];j++) calc(st[j]);
for(j=1;j<=st[0];j++) insert(st[j]);
if(cnt<m) ans=max(ans,n-i+1);
}
for(i=1;i<=n;i++)
{
it=S[p[i].col].upper_bound(p[i].x),b=(it==S[p[i].col].end()?nm+1:(*it));
it=S[p[i].col].lower_bound(p[i].x),a=(it==S[p[i].col].begin()?0:(*(--it)));
ans=max(ans,query(b-1)-query(p[i].x)),ans=max(ans,query(p[i].x-1)-query(a));
}
printf("%d\n",ans);
}
int main()
{
int T=rd();
while(T--) work();
return 0;
}

【BZOJ4548】小奇的糖果 set(链表)+树状数组的更多相关文章

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

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

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

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

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

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

  4. BZOJ4548 小奇的糖果

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

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

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

  6. 【BZOJ3295】【块状链表+树状数组】动态逆序对

    Description 对于序列A,它的逆序对数定义为满足i<j,且Ai>Aj的数对(i,j)的个数.给1到n的一个排列,按照某种顺序依次删除m个元素,你的任务是在每次删除一个元素之前统计 ...

  7. 求序列A中每个数的左边比它小的数的个数(树状数组)

    给定一个有N个正整数的序列A(N<=10^5,A[i]<=10^5),对序列中的每一个数,求出序列中它左边比它小的数的个数. 思路:树状数组的经典应用(裸题) #include <i ...

  8. [CSP-S模拟测试]:小P的单调数列(树状数组+DP)

    题目描述 小$P$最近喜欢上了单调数列,他觉得单调的数列具有非常多优美的性质.经过小$P$复杂的数学推导,他计算出了一个单调增数列的艺术价值等于该数列中所有书的总和.并且以这个为基础,小$P$还可以求 ...

  9. HH的项链题解(离线思想+链表+树状数组)

    本人第一篇博客重磅推出!!! 希望各位朋友以后多多捧场也多给写意见(我个人喜欢把题解写得啰嗦一点,因为这样方便理解,各位巨佬勿喷) 来讲一道提高+/省选-的骚题:HH的项链(这个HH你理解成皇后呵呵哈 ...

随机推荐

  1. linux下小试redis demo

    先启动  redis-server /etc/redis/redis.conf package com.test; import java.util.ArrayList; import java.ut ...

  2. swift初探(供objective c开发人员參考)

    6月初的wwdc苹果推出了一门新的开发语言swift.系统10.9.3以上安装xcode6 beta版就可以体验swift. 苹果公司做了尽可能多的努力让这门语言迅速成为一个工业级的有用编程语言,而不 ...

  3. Python 把u'\xca\xd3\xc6\xb5\xd7\xa5\xc8\xa1' 输出正常中文

    今天碰见从数据库读取出来数据是u'\xca\xd3\xc6\xb5\xd7\xa5\xc8\xa1',输出显示乱码,经常查询处理如下: 两种方式: 1. s = u'\xca\xd3\xc6\xb5\ ...

  4. Spark Streaming与Storm的对比及使用场景

    Spark Streaming与Storm都可以做实时计算,那么在做技术选型的时候到底应该选择哪个呢?通过下图可以从计算模型.计算延迟.吞吐量.事物.容错性.动态并行度等方方面进行对比. 对比点    ...

  5. 2017.8.9在虚拟机中安装linux系统

    0 安装前提 已经安装好VM,并且配置好,具体过程参看随笔:2017.8.5 VMware的介绍与安装 相关随笔:2017.8.5 Linux达人养成计划 I 需要知道的概念:VMWare,虚拟机,真 ...

  6. JAVA Eclipse如何重新设置工作空间workspace

    窗口-首选项-常规-启动和关闭,勾选启动时提示工作空间,然后移除现有的工作空间,最好也勾选启动时刷新工作空间   重启之后就可以设置工作空间了  

  7. Java虚拟机对锁优化所做的努力(读书笔记)

    锁偏向      是一种加锁操作的优化手段,他的核心思想是:如果一个线程获得了锁,那么就进入偏向模式,当这个线程再次请求锁时,无须在做任何同步操作,因此在几乎没有锁竞争的场合,偏向锁是比较好的优化效果 ...

  8. mysql_affected_rows的注意点

    取得最近一次与 link_identifier 关联的 INSERT,UPDATE 或 DELETE 查询所影响的记录行数. 1.执行成功,则返回受影响的行的数目,如果最近一次查询失败的话,函数返回 ...

  9. C中的C文件与h文件辨析

    简单的说其实要理解C文件与头文件(即.h)有什么不同之处,首先需要弄明白编译器的工作过程,一般说来编译器会做以下几个过程:       1.预处理阶段 2.词法与语法分析阶段 .编译阶段,首先编译成纯 ...

  10. jQuery.delegate() 函数详解

    delegate()函数用于为指定元素的一个或多个事件绑定事件处理函数. 此外,你还可以额外传递给事件处理函数一些所需的数据. 即使是执行delegate()函数之后新添加的元素,只要它符合条件,绑定 ...