牛客多校第十场 F Popping Balloons 线段树维护稀疏矩阵
题意:
给定一个稀疏矩阵,里面有若干个气球,让你横着开三枪,竖着开三枪,问最多能打爆多少气球,要求相同方向,相邻两枪必须间隔r。
题解:
横向记录每列有多少个气球,分别在哪行上。
然后把这个数据改造成以此点为左端点,此列,以及此行右r列,以及右2r列的信息。
纵向记录每行有多少个气球。
然后将此数据改造成以此点为下端点,此行,上r行,上2r行的信息。
将每行有多少个气球用线段树维护。
枚举竖着开枪的左端点,在线段树上删去那些竖着打爆的气球,然后询问线段树根节点,树上叶节点权值最大为几,就是横着三枪能打爆的最多气球数。
再把横着打爆的和竖着打爆的加起来维护最大值。
再把删掉的气球加回来。
由于矩阵为稀疏矩阵,因此保证在整个横向枚举过程,访问的节点是O(n)的。
#include<iostream>
#include<vector>
#define MAXN 100005
#define LL long long
using namespace std;
struct Node{
int l,r;
// int sum;
int maxx;
}node[MAXN<<]; int killy[MAXN];//选择此点为y轴下端点消灭的气球数
vector<int> killx[MAXN];//选择此点为x轴左端点能够消灭哪些气球 void build(int l,int r,int x){
node[x].l=l;
node[x].r=r;
if(l==r){
// node[x].sum=killy[l];
node[x].maxx=killy[l];
return ;
}else{
int mid=(l+r)/;
build(l,mid,x*);
build(mid+,r,x*+);
}
// node[x].sum=node[2*x].sum+node[2*x+1].sum;
node[x].maxx=max(node[*x].maxx,node[*x+].maxx);
return ;
}
void add(int id,int x,int num){
if(node[x].l==node[x].r){
// node[x].sum+=num;
node[x].maxx+=num;
return ;
}
if(id<=node[x*].r){
add(id,x*,num);
}else{
add(id,x*+,num);
}
// node[x].sum=node[2*x].sum+node[2*x+1].sum;
node[x].maxx=max(node[*x].maxx,node[*x+].maxx);
return ;
}
int main(){
int n,r;
int max_x=,max_y=;
scanf("%d %d",&n,&r); for(int i=;i<=n;i++){
int x,y;
scanf("%d %d",&x,&y);
x++;
y++;
max_x=max(max_x,x);
max_y=max(max_y,y); killy[y]++;
if(y-r>)killy[y-r]++;
if(y-r-r>)killy[y-r-r]++; killx[x].push_back(y);
if(x-r>)killx[x-r].push_back(y);
if(x-r-r>)killx[x-r-r].push_back(y);
}
build(,max_y,);
int sum=,ans=; // printf("%d\n",node[1].maxx);
// for(int i=1;i<=25;i++){
// printf("i:%d l:%d r:%d maxx:%d\n",i,node[i].l,node[i].r,node[i].maxx);
// } for(int i=;i<=max_x;i++){
sum=killx[i].size();
for(int j=;j<killx[i].size();j++){
// printf("%d\n",killx[i][j]);
add(killx[i][j],,-);
if(killx[i][j]-r>)add(killx[i][j]-r,,-);
if(killx[i][j]-r-r>)add(killx[i][j]-r-r,,-);
} // for(int kk=1;kk<=25;kk++){
// printf("l:%d r:%d maxx:%d\n",node[kk].l,node[kk].r,node[kk].maxx);
// } sum+=node[].maxx;
// printf("x:%d xkill:%d ykill:%d\n",i,killx[i].size(),node[1].maxx);
ans=max(sum,ans);
for(int j=;j<killx[i].size();j++){
add(killx[i][j],,);
if(killx[i][j]-r>)add(killx[i][j]-r,,);
if(killx[i][j]-r-r>)add(killx[i][j]-r-r,,);
} }
printf("%d\n",ans);
return ;
}
牛客多校第十场 F Popping Balloons 线段树维护稀疏矩阵的更多相关文章
- 牛客多校第四场sequence C (线段树+单调栈)
牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...
- 2019年牛客多校第四场 B题xor(线段树+线性基交)
题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...
- 2019牛客多校第四场C-sequence(单调栈+线段树)
sequence 题目传送门 解题思路 用单调栈求出每个a[i]作为最小值的最大范围.对于每个a[i],我们都要乘以一个以a[i]为区间内最小值的对应的b的区间和s,如果a[i] > 0,则s要 ...
- 牛客多校第七场 C Governing sand 线段树
题意: 有一个树林,树林中不同种类的树有不同的数量,高度,砍伐它们的价格.现在要求砍掉一些树,使得高度最高的树占剩下的树的总数的一半以上,求最小花费. 题解: 用线段树维护不同种类树的信息,叶子节点从 ...
- 牛客多校第三场 F Planting Trees
牛客多校第三场 F Planting Trees 题意: 求矩阵内最大值减最小值大于k的最大子矩阵的面积 题解: 矩阵压缩的技巧 因为对于我们有用的信息只有这个矩阵内的最大值和最小值 所以我们可以将一 ...
- 2019牛客多校第八场 F题 Flowers 计算几何+线段树
2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...
- 牛客多校第五场 F take
链接:https://www.nowcoder.com/acm/contest/143/F来源:牛客网 题目描述 Kanade has n boxes , the i-th box has p[i] ...
- 牛客多校第四场 F Beautiful Garden
链接:https://www.nowcoder.com/acm/contest/142/F来源:牛客网 题目描述 There's a beautiful garden whose size is n ...
- 牛客多校第十场 A Rikka with Lowbit 线段树
链接:https://www.nowcoder.com/acm/contest/148/A来源:牛客网 题目描述 Today, Rikka is going to learn how to use B ...
随机推荐
- web框架express学习一
服务端 node app.jsapp.jslet express = require("express"); let http = require("http" ...
- js正则删除字符串中的部分内容
// 例如 let a = `(ID)444` a.replace(/\(ID\)/ig, '') // 结果 "444"
- Vue学习笔记【15】——Vue实例的生命周期
生命周期与生命周期钩子 什么是生命周期:从Vue实例创建.运行.到销毁期间,总是伴随着各种各样的事件,这些事件,统称为生命周期! 生命周期钩子:就是生命周期事件的别名而已: 生命周期钩子 = 生命周期 ...
- js类数组转数组的方法(ArrayLike)
1. 什么是类数组ArrayLike(类数组 就是一个普通的 js对象) 类数组对象必须含有 length 属性,且元素属性名必须是数值或者可转换为数值的字符. 类数组对象不是数组对象,所以没有数 ...
- sqlmap用户手册详解【实用版】
网上的sqlmap教程很多,但是我自己备忘小笔记都是在我的电脑上存着了,万一我要出去玩的时候,有点忘了,还得再百度翻翻,还不如发到我自己知乎上,忘了立马一看就记着了.虽说我的sqlmap备忘小笔记汇总 ...
- VC内联汇编,引用程序中的变量
int a=5; //变量a _asm { mov eax,a; //将变量a的值放入寄存器eax add eax,eax; //相当于a=a+a mov a,eax; // ...
- 关于python语言学习心得
最近又开始学习代码了,中途停顿了2个月左右,学习贵在坚持. 内心非常渴望学会一门编程语言,对代码目前来说还不是排斥. 也没有什么好的学习方法,只是按照同事说的,买了一本书籍来,边看边练习,先熟悉它的语 ...
- Dubbo入门到精通学习笔记(二):Dubbo管理控制台、使用Maven构建Dubbo的jar包、在Linux上部署Dubbo privider服务(shell脚本)、部署consumer服务
文章目录 Dubbo管理控制台 1.Dubbo管理控制台的主要作用: 2.管理控制台主要包含: 3.管理控制台版本: 安装 Dubbo 管理控制台 使用Maven构建Dubbo服务的可执行jar包 D ...
- 数据挖掘 FP-tree算法C++实现及源码
FP-growth挖掘算法 步骤一 扫描数据库,扫描数据库一次,得到频繁1-项集,把项按支持度递减排序,再一次扫描数据库,建立FP-tree 步骤二 对每个项,生成它的 条件模式库 步骤三 用条件模式 ...
- JAVA 字符串索引
String类的substring()方法 截取字符串,在java语言中的用法 1. public String substring(int beginIndex) 返回一个新字符串,它是此字符 ...