JZOJ 1495. 宝石
题目大意
用边长为 \(k\) 的正方形在平面内覆盖,求它能覆盖的最大点权和
思路
\(60\) 分:其实很容易想到按它们的横坐标先后排序,然后单调队列维护。复杂度 \(O(n k \log k)\)
然而考试时我直接修改了队列,导致 \(WA\) 到了 \(10\) 分!改后又由于各种问题使它只 \(TLE\) 到 \(50\) 分
\(100\) 分:
接下来讲解两种做法(本质上是一样的)
一:我们圈出了横坐标差为 \(k\) 的一个区间,如图:

考虑处理纵坐标
很容易想到线段树维护纵坐标各处权值
我们这 \(t_i\) 表示纵坐标为 \([i..{i+k}]\) 上的权值和(不用考虑横坐标了)
每插入一个点,它会对 \(t\) 中 \(i..{i-k}\) 都产生贡献
那么我们区间修改即可
每次修改后,取全局最大值
线段树同时维护最大值即可
\(Code\)
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
const int N = 5e4 + 5;
int m , n , k , ans;
struct point{
int a , b , c;
}a[N] , d[N];
inline bool cmp(point x , point y){return x.a < y.a ? 1 : (x.a == y.a ? x.b < y.b : 0);}
struct Segment_tree{
int tag[N << 2] , mx[N << 2];
void update(int k , int l , int r , int x , int y , int v)
{
if (x <= l && r <= y)
{
tag[k] += v;
return;
}
int mid = (l + r) >> 1;
if (x <= mid) update(k << 1 , l , mid , x , y , v);
if (y > mid) update(k << 1 | 1 , mid + 1 , r , x , y , v);
mx[k] = max(mx[k << 1] + tag[k << 1] , mx[k << 1 | 1] + tag[k << 1 | 1]);
}
}seg;
int main()
{
scanf("%d%d%d" , &m , &n , &k);
for(register int i = 1; i <= n; i++) scanf("%d%d%d" , &a[i].a , &a[i].b , &a[i].c);
sort(a + 1 , a + n + 1 , cmp);
int h = 0 , t = 0;
for(register int i = 1; i <= n; i++)
{
while (a[i].a - d[h].a > k && h <= t) seg.update(1 , 1 , m , max(1 , d[h].b - k) , d[h].b , -d[h].c) , h++;
if (h == 0) h++;
d[++t] = a[i] , seg.update(1 , 1 , m , max(1 , a[i].b - k) , a[i].b , a[i].c);
ans = max(ans , seg.mx[1]);
}
printf("%d" , ans);
}
二:扫描线做法
先转化成扫描线可做的模型
我们把以一个点为左下角的矩形画出来,并给纵条边赋上边权为它的正(负)点权,表示它对这个矩形产生的贡献
如图:

那么在一个矩形内,含有的纵向线段(只要有一部分)权值之和就是可能的答案
那么我们在扫描时就把纵向线段权值加入线段树中
注意加入后它是一个区间,那么多个区间重叠的部分就是我们矩形的贡献
于是我们维护每个矩形的贡献最大值就变成了维护最大值(一个矩形是我们能覆盖的最大的二维区间,所以只取每个矩形的贡献最大值)
而矩形的靠右的纵向边是不能纳入本矩形的贡献,所以它要在 \(X=x+k+1\) 的直线上
扫描线扫过靠右的纵向边后,靠左的纵向边就不能再产生贡献了,所以其值设为负的
\(Code\)
#include<cstdio>
#include<iostream>
#include<algorithm>
using namespace std;
typedef long long LL;
const int N = 5e4 + 5;
int m , n , k , ans;
struct line{
int x , l , r , v;
}l[N << 2];
inline bool cmp(line x , line y){return x.x < y.x ? 1 : (x.x == y.x ? x.v < y.v : 0);}
struct Segment_tree{
int tag[N << 2] , mx[N << 2];
void update(int k , int l , int r , int x , int y , int v)
{
if (y < l || r < x) return;
if (x <= l && r <= y)
{
tag[k] += v;
return;
}
int mid = (l + r) >> 1;
if (x <= mid) update(k << 1 , l , mid , x , y , v);
if (y > mid) update(k << 1 | 1 , mid + 1 , r , x , y , v);
mx[k] = max(mx[k << 1] + tag[k << 1] , mx[k << 1 | 1] + tag[k << 1 | 1]);
}
}seg;
int main()
{
scanf("%d%d%d" , &m , &n , &k);
int x , y , z;
for(register int i = 1; i <= n; i++)
{
scanf("%d%d%d" , &x , &y , &z);
l[(i << 1) - 1] = (line){x , y , y + k , z};
l[i << 1] = (line){x + k + 1 , y , y + k , -z};
}
n <<= 1;
sort(l + 1 , l + n + 1 , cmp);
for(register int i = 1; i <= n; i++)
{
seg.update(1 , 1 , m , l[i].l , l[i].r , l[i].v);
ans = max(ans , seg.mx[1] + seg.tag[1]);
}
printf("%d" , ans);
}
其实两者的时间复杂度是几乎相同的(因为你发现两者代码也几乎相同)
感性地理解并发现,后者速度似乎更快(常数小)
所以我打的两个都差不多
后者思考方式不一样
建议两者都思考一下
JZOJ 1495. 宝石的更多相关文章
- 【BFS】HDU 1495
直达–> HDU 1495 非常可乐 相似题联动–>POJ 3414 Pots 题意:中文题,不解释. 思路:三个杯子倒来倒去,最后能让其中两个平分即可.可能性六种.判定的时候注意第三个杯 ...
- BZOJ1190[HNOI2007]梦幻岛宝石
Description 给你N颗宝石,每颗宝石都有重量和价值.要你从这些宝石中选取一些宝石,保证总重量不超过W,且总价值最大为,并输出最大的总价值.数据范围:N<=100;W<=2^30, ...
- HDU 1495 非常可乐
http://acm.hust.edu.cn/vjudge/contest/view.action?cid=103711#problem/M /*BFS简单题 链接地址: http://acm.hdu ...
- BZOJ-1625 宝石手镯 01背包(傻逼题)
傻逼题,懒得打,复制蛋蛋的.. 1625: [Usaco2007 Dec]宝石手镯 Time Limit: 5 Sec Memory Limit: 64 MB Submit: 1076 Solved: ...
- BZOJ_1625_ [Usaco2007_Dec]_宝石手镯_(01背包)
描述 http://www.lydsy.com/JudgeOnline/problem.php?id=1625 01背包裸题. p.s.随便点开一道就是水题... 分析 ... #include &l ...
- HDU 1495 非常可乐 BFS 搜索
http://acm.hdu.edu.cn/showproblem.php?pid=1495 题目就不说了, 说说思路! 倒可乐 无非有6种情况: 1. S 向 M 倒 2. S 向 N 倒 3. N ...
- BZOJ 1625: [Usaco2007 Dec]宝石手镯( dp )
最裸的01背包.... --------------------------------------------------------------------- #include<cstdio ...
- PHP SPL他们留下的宝石
Rafael Dohms 上面的篇文章 让我为之惊艳,忍不住就翻译了下来,同一时候补充了部分内容. SPL,PHP 标准库(Standard PHP Library) ,此从 PHP 5.0 起内置的 ...
- Linux:闪光的宝石,智慧 (在)
Linux:闪光的宝石,智慧的结晶(上) 老实说,这十几天以来.因为我违反了"家规",又被断网处罚(拔掉网线).没收手机与老年证(不许出家门). 因此.我平日里仅仅能面对一篇文章& ...
- Linux:闪光的宝石,智慧(下一个)
2005年4月7日.Linus Torvalds公布了一款新型通用工具软件包,叫做"Git"(the Git source code management system).&quo ...
随机推荐
- <三>function函数对象类型的应用示例
std::function是一组函数对象包装类的模板,实现了一个泛型的回调机制.function与函数指针比较相似,优点在于它允许用户在目标的实现上拥有更大的弹性,即目标既可以是普通函数,也可以是函数 ...
- linux常用命令精讲
一.虚拟机三种网卡模式 1 桥接 相当于虚拟机和真机之间架了一座桥 2 NAT 虚拟系统借助 NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网(常用vm8) 3 仅主机 虚拟机和物理机在一 ...
- Spring 6 源码编译和高效阅读源码技巧分享
一. 前言 Spring Boot 3 RELEASE版本于 2022年11月24日 正式发布,相信已经有不少同学开始准备新版本的学习了,不过目前还不建议在实际项目中做升级,毕竟还有很多框架和中间件没 ...
- PhaApi NOTORM 实现分表分库
通过自增ID取模要分表的数量,便可得到表名.例如log表分成100张表:log_1,log2...,log100. 每次数据库CURD都先通过获取ID分配到相对应的表,例如:id=66,取模后的结果是 ...
- java中的自增运算
本文主要阐明java中的自增运算 1.当i ++ 与 ++ i作为单独语句时,作用与i = i +1一样 2.当赋值时,结果就不一样了 temp = i ++: 操作顺序:1)temp = i: 2) ...
- 编译安装nmon
nmon 是什么? nmon(Nigel's performance Monitor for Linux)是一种Linux性能监视工具,当前它支持 Power/x86/x86_64/Mainframe ...
- 在IQuery中使用除法提示"Numeric value does not fit in a System.Decimal"
起因 有个需求是需要汇总(单耗=单件用量*1+损耗率)的值,由于现在我们数据库中存的XX率都是放大了一百倍(即10%数据库存的是10),然后就很自然的写了个linq汇总如下 materialOrder ...
- [编程基础] C++多线程入门2-连接和分离线程
原始C++标准仅支持单线程编程.新的C++标准(称为C++11或C++0x)于2011年发布.在C++11中,引入了新的线程库.因此运行本文程序需要C++至少符合C++11标准. 文章目录 2 连接和 ...
- 在Mac OS上将Node.js连接到XAMPP MySQL服务器一直报错error connecting: Error: connect ECONNREFUSED
以下為通過node.js連線本機mysql資料庫的方法: var mysql = require('mysql'); var connection = mysql.createConnection({ ...
- NLP知识图谱项目合集(信息抽取、文本分类、图神经网络、性能优化等)
NLP知识图谱项目合集(信息抽取.文本分类.图神经网络.性能优化等) 这段时间完成了很多大大小小的小项目,现在做一个整体归纳方便学习和收藏,有利于持续学习. 1. 信息抽取项目合集 1.PaddleN ...