当前位置:网站首页>P5019 [NOIP2018 提高组] 铺设道路
P5019 [NOIP2018 提高组] 铺设道路
2022-07-31 12:49:00 【WDLieqi】
[NOIP2018 提高组] 铺设道路
题目背景
NOIP2018 提高组 D1T1
题目描述
春春是一名道路工程师,负责铺设一条长度为 n n n 的道路。
铺设道路的主要工作是填平下陷的地表。整段道路可以看作是 n n n 块首尾相连的区域,一开始,第 i i i 块区域下陷的深度为 d i d_i di 。
春春每天可以选择一段连续区间 [ L , R ] [L,R] [L,R] ,填充这段区间中的每块区域,让其下陷深度减少 1 1 1。在选择区间时,需要保证,区间内的每块区域在填充前下陷深度均不为 0 0 0 。
春春希望你能帮他设计一种方案,可以在最短的时间内将整段道路的下陷深度都变为 0 0 0 。
输入格式
输入文件包含两行,第一行包含一个整数 n n n,表示道路的长度。 第二行包含 n n n 个整数,相邻两数间用一个空格隔开,第 i i i 个整数为 d i d_i di 。
输出格式
输出文件仅包含一个整数,即最少需要多少天才能完成任务。
样例 #1
样例输入 #1
6
4 3 2 5 3 5
样例输出 #1
9
提示
【样例解释】
一种可行的最佳方案是,依次选择:
[ 1 , 6 ] [1,6] [1,6]、 [ 1 , 6 ] [1,6] [1,6]、 [ 1 , 2 ] [1,2] [1,2]、 [ 1 , 1 ] [1,1] [1,1]、 [ 4 , 6 ] [4,6] [4,6]、 [ 4 , 4 ] [4,4] [4,4]、 [ 4 , 4 ] [4,4] [4,4]、 [ 6 , 6 ] [6,6] [6,6]、 [ 6 , 6 ] [6,6] [6,6]。
【数据规模与约定】
对于 30 % 30\% 30% 的数据, 1 ≤ n ≤ 10 1 ≤ n ≤ 10 1≤n≤10 ;
对于 70 % 70\% 70% 的数据, 1 ≤ n ≤ 1000 1 ≤ n ≤ 1000 1≤n≤1000 ;
对于 100 % 100\% 100% 的数据, 1 ≤ n ≤ 100000 , 0 ≤ d i ≤ 10000 1 ≤ n ≤ 100000 , 0 ≤ d_i ≤ 10000 1≤n≤100000,0≤di≤10000 。
思路
这道题的正规思路是用贪心的办法来进行求解,复杂度位O(n),但这里我的解题方法是线段树,复杂度O(nlogn),正规解法在原题里面的题解可以看到。
正文来了
因为我们可以进行操作的前提条件是连续区间内不能有等于零的数,所以选的区间里面必须要全部大于零。通过观察我们很容易的发现将最小的数减为零后可以将原区间分为左右两个区间例如:
45233 4 5 2 3 3 45233 变为 23011 2 3 0 1 1 23011 然后就可变为 23 2 3 23 和 11 1 1 11
所以通过不断划分区间来让全部的数变成 0
接下来是线段树维护的信息
我们要完成上述的操作就要知道两个信息,最小值和最小值的下标,所以我们的线段树记录的就是最小值和最小值的下标。
代码
#include <bits/stdc++.h>
using namespace std;
#define IOS \ ios::sync_with_stdio(false); \ cin.tie(0); \ cout.tie(0);
#define P acos(-1);
typedef long long LL;
typedef unsigned long long ULL;
#define PII pair<int, int>
#define PDD pair<double, double>
#define Pll pair<LL, LL>
typedef unsigned long long ULL;
const double eps = 1e-7;
const int N = 1e5 + 10, M = 1e6 + 10, mod = 998244353;
const int inf = 0x3f3f3f3f;
int dx[] = {
1, -1, 0, 0, -1, 1, 1, -1}, dy[] = {
0, 0, -1, 1, -1, -1, 1, 1};
int lowbit(int x) {
return (x & -x); };
struct node
{
int l, r;
int minn, add, pos;
}tr[N * 4];
int a[N];
int n, sum;
queue<PII> q;
void pushup(int u)
{
if (tr[u << 1].minn < tr[u << 1 | 1].minn)
{
tr[u].minn = tr[u << 1].minn;
tr[u].pos = tr[u << 1].pos;
}
else
{
tr[u].minn = tr[u << 1 | 1].minn;
tr[u].pos = tr[u << 1 | 1].pos;
}
}
void pushdown(int u)
{
auto &root = tr[u], &left = tr[u << 1], &right = tr[u << 1 | 1];
if (root.add)
{
left.add += root.add, left.minn -= root.add;
right.add += root.add, right.minn -= root.add;
root.add = 0;
}
}
void build(int u, int l, int r)
{
if (l == r) tr[u] = {
l, r, a[l], 0, l};
else
{
tr[u] = {
l, r};
int mid = l + r >> 1;
build(u << 1, l, mid), build(u << 1 | 1, mid + 1, r);
pushup(u);
}
}
void modify(int u, int l, int r, int d)
{
if (tr[u].l >= l && tr[u].r <= r)
{
tr[u].minn -= d;
tr[u].add += d;
return;
}
int mid = tr[u].l + tr[u].r >> 1;
pushdown(u);
if (mid >= l) modify(u << 1, l, r, d);
if (mid < r) modify(u << 1 | 1, l, r, d);
pushup(u);
}
node query(int u, int l, int r)
{
if (tr[u].l >= l && tr[u].r <= r) return tr[u];
int mid = tr[u].l + tr[u].r >> 1;
pushdown(u);
node ans1, ans2;
if (mid >= r) return query(u << 1, l, r);
else if (mid < l) return query(u << 1 | 1, l, r);
ans1 = query(u << 1, l, r), ans2 = query(u << 1 | 1, l, r);
if (ans1.minn < ans2.minn) return ans1;
return ans2;
}
void solve()
{
scanf("%d", &n);
for (int i = 1; i <= n; i ++ ) scanf("%d", &a[i]);
build(1, 1, n);
q.push({
1, n});
node ans;
while (q.size())
{
int f = q.front().first, g = q.front().second;
q.pop();
ans = query(1, f, g);
sum += ans.minn;
if (ans.minn) modify(1, f, g, ans.minn);
if (ans.pos > f) q.push({
f, ans.pos - 1});
if (ans.pos < g) q.push({
ans.pos + 1, g});
}
printf("%d", sum);
}
int main()
{
int T = 1;
//scanf("%d", &T);
while (T -- )
{
solve();
}
return 0;
}
O(n) 复杂度正规解法
大坑带小坑,小坑会被大坑带着填满。
大坑会减少两者的差,相当于这部分是免费的
#include <bits/stdc++.h>
using namespace std;
#define IOS \ ios::sync_with_stdio(false); \ cin.tie(0); \ cout.tie(0);
#define P acos(-1);
typedef long long LL;
typedef unsigned long long ULL;
#define PII pair<int, int>
#define PDD pair<double, double>
#define Pll pair<LL, LL>
typedef unsigned long long ULL;
const double eps = 1e-7;
const int N = 1e5 + 10, M = 1e6 + 10, mod = 998244353;
const int inf = 0x3f3f3f3f;
int dx[] = {
1, -1, 0, 0, -1, 1, 1, -1}, dy[] = {
0, 0, -1, 1, -1, -1, 1, 1};
int lowbit(int x) {
return (x & -x); };
int n, a[N];
LL ans = 0;
void solve()
{
cin >> n;
for (int i = 1; i <= n; i ++ ) cin >> a[i];
for (int i = 2; i <= n; i ++ )
if (a[i] > a[i - 1]) ans += a[i] - a[i - 1];
cout << ans + a[1];
}
int main()
{
int T = 1;
// scanf("%d", &T);
while (T--)
{
solve();
}
return 0;
}
边栏推荐
- ERROR 1819 (HY000) Your password does not satisfy the current policy requirements
- 基于verilog的CRC校验(汇总)
- Markdown编辑器语法
- Google Chrome(谷歌浏览器)安装使用
- 立一个flag
- [core]-ARMV7-A, ARMV8-A, ARMV9-A Architecture Introduction "Recommended Collection"
- IDEA的database使用教程(使用mysql数据库)
- 聊聊 SAP 产品 UI 上的消息显示机制
- 【OpenCV】-边缘检测汇总示例
- 深圳某游戏研发公司每个工位都装监控,网友:堪比“坐牢”!
猜你喜欢
随机推荐
The function of SQL GROUP BY dependence
ERROR 1819 (HY000) Your password does not satisfy the current policy requirements
基于生物激励神经网络的室内实时激光SLAM控制方法
golang八股文整理(持续搬运)
三相PWM整流器预测直接功率控制
sqlalchemy 判断一个array 类型的字段是否和一个array有至少一个一致的数据
PAT exam summary (exam experience)
NameNode故障处理的两种方法
SAP 电商云 Spartacus UI 和 Accelerator UI 里的 ASM 模块
The 2nd activity of the TOGAF10 Standard Reading Club continues wonderfully, and the highlights will be reviewed!
chroot命令
Json和对象之间转换的封装(Gson)
ASM module in SAP Ecommerce Cloud Spartacus UI and Accelerator UI
关于我放弃考研这件事儿
ERROR 2003 (HY000) Can‘t connect to MySQL server on ‘localhost3306‘ (10061)
深度学习基本概念
使用openssl命令生成证书和对应的私钥,私钥签名,公钥验签
PyQt5快速开发与实战 10.1 获取城市天气预报
【Shader】Shader官方示例[通俗易懂]
Fully Dynamically Constrained Robot Efficient Time-Optimal Trajectory Planning









