题意:

给定一个稀疏矩阵,里面有若干个气球,让你横着开三枪,竖着开三枪,问最多能打爆多少气球,要求相同方向,相邻两枪必须间隔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 线段树维护稀疏矩阵的更多相关文章

  1. 牛客多校第四场sequence C (线段树+单调栈)

    牛客多校第四场sequence C (线段树+单调栈) 传送门:https://ac.nowcoder.com/acm/contest/884/C 题意: 求一个$\max {1 \leq l \le ...

  2. 2019年牛客多校第四场 B题xor(线段树+线性基交)

    题目链接 传送门 题意 给你\(n\)个基底,求\([l,r]\)内的每个基底是否都能异或出\(x\). 思路 线性基交板子题,但是一直没看懂咋求,先偷一份咖啡鸡板子写篇博客吧~ 线性基交学习博客:传 ...

  3. 2019牛客多校第四场C-sequence(单调栈+线段树)

    sequence 题目传送门 解题思路 用单调栈求出每个a[i]作为最小值的最大范围.对于每个a[i],我们都要乘以一个以a[i]为区间内最小值的对应的b的区间和s,如果a[i] > 0,则s要 ...

  4. 牛客多校第七场 C Governing sand 线段树

    题意: 有一个树林,树林中不同种类的树有不同的数量,高度,砍伐它们的价格.现在要求砍掉一些树,使得高度最高的树占剩下的树的总数的一半以上,求最小花费. 题解: 用线段树维护不同种类树的信息,叶子节点从 ...

  5. 牛客多校第三场 F Planting Trees

    牛客多校第三场 F Planting Trees 题意: 求矩阵内最大值减最小值大于k的最大子矩阵的面积 题解: 矩阵压缩的技巧 因为对于我们有用的信息只有这个矩阵内的最大值和最小值 所以我们可以将一 ...

  6. 2019牛客多校第八场 F题 Flowers 计算几何+线段树

    2019牛客多校第八场 F题 Flowers 先枚举出三角形内部的点D. 下面所说的旋转没有指明逆时针还是顺时针则是指逆时针旋转. 固定内部点的答案的获取 anti(A)anti(A)anti(A)或 ...

  7. 牛客多校第五场 F take

    链接:https://www.nowcoder.com/acm/contest/143/F来源:牛客网 题目描述 Kanade has n boxes , the i-th box has p[i] ...

  8. 牛客多校第四场 F Beautiful Garden

    链接:https://www.nowcoder.com/acm/contest/142/F来源:牛客网 题目描述 There's a beautiful garden whose size is n ...

  9. 牛客多校第十场 A Rikka with Lowbit 线段树

    链接:https://www.nowcoder.com/acm/contest/148/A来源:牛客网 题目描述 Today, Rikka is going to learn how to use B ...

随机推荐

  1. Cross platform

    值得学习的C/C++语言开源项目 (1)ACE 庞大.复杂,适合大型项目.开源.免费,不依赖第三方库,支持跨平台. http://www.cs.wustl.edu/~schmidt/ACE.html ...

  2. Windows 屏幕保护程序

    { 创建一个win32 窗口项目,不是控制台的 把exe改为src文件 复制到windows目录下 ok }

  3. C#中ArrayList 、Array与、string、string[]数组的相关转换

    一.ArrayList 与 string.string[]数组的转换 1.ArrayList 转换为 string[] : ArrayList list = new ArrayList(); list ...

  4. Robot Framework:随机数

    脚本 随机数 # 随机生成几位随机数 ${num} set variable 6 ${random} evaluate "".join(random.sample(string.l ...

  5. 入门级_Tensorflow网络搭建

    Tensorflow如何搭建神经网络 1.基本概念 基于Tensorflow的神经网络:用张量表示数据,用计算图搭建神经网络,用会话执行计算图,优化线上的权重(参数),得到模型 张量:张量就是多维数据 ...

  6. 批处理禁止指定的IE的加载项

    步骤: 1.查找插件对应的 CLSID 获取 HKCU\Software\Microsoft\Windows\CurrentVersion\Ext\Stats 下的 CLSID, 然后在 HKCR\C ...

  7. ajax url地址

    当前网址 http://localhost:8080/exam_paper/402881ec5c3924ec015c394ee4210000/set_questions ajax请求url var u ...

  8. C#比较时间大小(时分)

    比较时间大小(时分)    string st1="12:13";    string st2="14:14";    DateTime dt1=Convert ...

  9. Keepalived 双主虚拟路由配置实例

    Keepalived 双主虚拟路由配置实例 演示前说明: 2台centos7.2 主机:node-00,node-01 VIP1:10.1.38.19预定node-00占有 VIP2:10.1.38. ...

  10. Java 8 终于支持 Docker !

    ];      v.add(b);      Runtime rt = Runtime.getRuntime();      System.out.println( "free memory ...