P5019 铺设道路 (NOIP2018)
2024-09-06 08:07:33
NOIP2013原题
貌似官方数据都是一模一样的
以前写过竟然毫无印象?
考场上自己瞎JB推结论
显然,如果连续的两端区间可以左边区间减 k 次,右边区间也减 k 次
那么把两个区间合并起来一起减 k 次一定是更优的
所以先考虑把整个区间拿来减几次,显然最多减的次数就是整个区间的最小值
然后此时最小值已经为零了,以最小值的位置分成左右两个区间继续同样处理就好了
如果每个区间都扫一遍最小值复杂度可以卡成 $O(n^2)$,(单调序列)
所以区间最小值容易想到ST表
然后复杂度 $O(nlog_n)$ (预处理ST表的复杂度)
话说官方数据 $O(n^2)$ 也能过....
#include<iostream>
#include<cstdio>
#include<algorithm>
#include<cmath>
#include<cstring>
using namespace std;
typedef long long ll;
inline int read()
{
int x=,f=; char ch=getchar();
while(ch<''||ch>'') { if(ch=='-') f=-; ch=getchar(); }
while(ch>=''&&ch<='') { x=(x<<)+(x<<)+(ch^); ch=getchar(); }
return x*f;
}
const int N=2e5+;
int n,a[N],pos[N][],Log[N];
ll ans;
void pre()//预处理ST表
{
Log[]=-; for(int i=;i<=n;i++) Log[i]=Log[i>>]+;
for(int i=;i<=n;i++) pos[i][]=i;
for(int i=;(<<i)<=n;i++)
for(int j=;j+(<<(i-))<=n;j++)
{
if(a[ pos[j][i-] ]>a[ pos[j+(<<(i-))][i-] ]) pos[j][i]=pos[j+(<<(i-))][i-];
else pos[j][i]=pos[j][i-];
}
}
inline int query(int l,int r)//区间求最小值
{
int k=Log[r-l+];
if(a[ pos[l][k] ]>a[ pos[r-(<<k)+][k] ]) return pos[r-(<<k)+][k];
return pos[l][k];
}
void f(int l,int r,int tot)//递归处理左右区间,tot是当前已经进行的操作次数
{
if(l>r) return;
int t=query(l,r);
ans+=a[t]-tot;
f(l,t-,a[t]); f(t+,r,a[t]);
}
int main()
{
freopen("road.in","r",stdin);
freopen("road.out","w",stdout);
n=read();
for(int i=;i<=n;i++) a[i]=read();
pre();
f(,n,);
cout<<ans<<endl;
return ;
}
最新文章
- Struts的拦截器
- uva 107 - The Cat in the Hat
- uboot环境变量与内核MTD分区关系
- I/O复用-select模型
- 6、第六课,js jquery20150928
- Qt:基于TCP和UDP的局域网P2P(局域网)通讯封装
- EasyUI - Messager消息框
- VS2012的安装项目只能用InstallShield Limited Edition
- POJ 2231 Moo Volume
- PyTorch官方中文文档:自动求导机制
- django/python日志logging 的配置以及处理
- const修饰指针+volatile +restrict
- django channle的使用
- C#操作DataTable类
- Python6 - 函数总结
- luogu P2015 二叉苹果树
- SQL 二
- UVALive 6529 Eleven 区间dp
- Oracle 性能调优案例(代码级别)
- dirname 和 basename