[CSP-S模拟测试]:F(DP+线段树)
题目传送门(内部题49)
输入格式
第一行四个整数$n,q,a,b$。
接下来$n$行每行一个整数$p_i$。
输出格式
一行一个整数表示答案。
样例
样例输入:
10 3 3 7
样例输出:
数据范围与提示
对于$30\%$的数据:$n,q\leqslant 2,000$
对于所有数据:
$1\leqslant n,q\leqslant {10}^5$
$1\leqslant p_i\leqslant n$
题解
首先,我们考虑$30\%$的算法怎么办?
考虑$DP$,定义$dp[i][j]$表示到了第$i$步,一个指针在$p_i$,另一个指针在$j$的最短步数。
那么我们可以里出状态转移方程:
$\alpha.dp[i][j]=dp[i-1][j]+|p_i-p_{i-1}|$(上一次和这一次移动的是一个指针)
$\beta.dp[i][p_{i-1}]=dp[i-1][j]+|p_i-j|$(上一次和这一次移动的不是一个指针)
那么我们接着考虑如何优化。
发现转移$\alpha$其实就是将整个区间都加了$|p_i-p_{i-1}|$,而转移$\beta$我们可以维护$dp[i][j]+j$和$dp[i][j]-j$的最小值即可。
所以考虑线段树优化,即可得到满分。
时间复杂度:$\Theta(n\log n)$。
期望得分:$100$分。
实际得分:$100$分。
代码时刻
#include<bits/stdc++.h>
#define L(x) x<<1
#define R(x) x<<1|1
using namespace std;
int n,q,a,b;
int p[100001];
long long tr[4][400001];
void pushup(int x)
{
tr[0][x]=min(tr[0][L(x)],tr[0][R(x)]);
tr[1][x]=min(tr[1][L(x)],tr[1][R(x)]);
tr[2][x]=min(tr[2][L(x)],tr[2][R(x)]);
}
void pushdown(int x)
{
if(!tr[3][x])return;
tr[0][L(x)]+=tr[3][x];
tr[0][R(x)]+=tr[3][x];
tr[1][L(x)]+=tr[3][x];
tr[1][R(x)]+=tr[3][x];
tr[2][L(x)]+=tr[3][x];
tr[2][R(x)]+=tr[3][x];
tr[3][L(x)]+=tr[3][x];
tr[3][R(x)]+=tr[3][x];
tr[3][x]=0;
}
void build(int x,int l,int r)
{
if(l==r)
{
if(l==b)
{
tr[0][x]=0;
tr[1][x]=l;
tr[2][x]=-l;
}
return;
}
int mid=(l+r)>>1;
build(L(x),l,mid);
build(R(x),mid+1,r);
pushup(x);
}
void change(int x,int l,int r,int w,long long k)
{
if(l==r)
{
tr[0][x]=min(tr[0][x],k);
tr[1][x]=tr[0][x]+l;
tr[2][x]=tr[0][x]-l;
return;
}
int mid=(l+r)>>1;
pushdown(x);
if(w<=mid)change(L(x),l,mid,w,k);
else change(R(x),mid+1,r,w,k);
pushup(x);
}
long long ask1(int x,int l,int r,int L,int R)
{
if(R<l||r<L)return 200209230020020923;
if(L<=l&&r<=R)return tr[2][x];
int mid=(l+r)>>1;
pushdown(x);
return min(ask1(L(x),l,mid,L,R),ask1(R(x),mid+1,r,L,R));
}
long long ask2(int x,int l,int r,int L,int R)
{
if(R<l||r<L)return 200209230020020923;
if(L<=l&&r<=R)return tr[1][x];
int mid=(l+r)>>1;
pushdown(x);
return min(ask2(L(x),l,mid,L,R),ask2(R(x),mid+1,r,L,R));
}
int main()
{
scanf("%d%d%d%d",&n,&q,&a,&b);
memset(tr[0],0x3f,sizeof(tr[0]));
memset(tr[1],0x3f,sizeof(tr[1]));
memset(tr[2],0x3f,sizeof(tr[2]));
build(1,1,n);
for(int i=1;i<=q;i++)
{
scanf("%d",&b);
tr[0][0]=min(ask1(1,1,n,1,b)+b,ask2(1,1,n,b,n)-b);
tr[0][1]+=abs(a-b);
tr[1][1]+=abs(a-b);
tr[2][1]+=abs(a-b);
tr[3][1]+=abs(a-b);
change(1,1,n,a,tr[0][0]);
a=b;
}
cout<<tr[0][1]<<endl;
return 0;
}
rp++
[CSP-S模拟测试]:F(DP+线段树)的更多相关文章
- [CSP-S模拟测试]:bird(线段树优化DP)
题目传送门(内部题89) 输入格式 第一行两个数$n$和$k$,分别表示小鸟的只数和$R$装弹时间.接下来$n$行,每行两个数$l,r$表示$n$只小鸟初始时的头和尾的$x$坐标. 输出格式 输出一个 ...
- [CSP-S模拟测试]:Weed(线段树)
题目描述 $duyege$的电脑上面已经长草了,经过辨认上面有金坷垃的痕迹.为了查出真相,$duyege$准备修好电脑之后再进行一次金坷垃的模拟实验.电脑上面有若干层金坷垃,每次只能在上面撒上一层高度 ...
- [CSP-S模拟测试]:光线追踪(线段树)
题目背景 初中时的乔猫试着组建了$NEWorld$开发组,可是不久之后却因为合作上的问题(和乔猫工程水平差,代码混乱的问题),开发组成员之间常常产生矛盾,关系越来越不如以前......一年下来,受到长 ...
- [CSP-S模拟测试]:椎(线段树维护区间最值和单调栈)
题目描述 虽不能至,心向往之. $Treap=Tree+Heap$ 椎$=$树$+$堆 小$\pi$学习了计算机科学中的数据结构$Treap$. 小$\pi$知道$Treap$指的是一种树. 小$\p ...
- [CSP-S模拟测试]:string(线段树)
题目描述 给定一个由小写字母组成的字符串$s$. 有$m$次操作,每次操作给定$3$个参数$l,r,x$. 如果$x=1$,将$s[l]~s[r]$升序排序: 如果$x=0$,将$s[l]~s[r]$ ...
- [CSP-S模拟测试]:Permutation(线段树+拓扑排序+贪心)
题目描述 你有一个长度为$n$的排列$P$与一个正整数$K$你可以进行如下操作若干次使得排列的字典序尽量小对于两个满足$|i−j|\geqslant K$且$|P_i−P_j|=1$的下标$i$与$j ...
- [CSP-S模拟测试]:f(Trie树+二分答案+meet in middle+two pointers)
题目传送门(内部题67) 输入格式 第一行,三个整数$n$.$k$.$p$.第二行,$n$个自然数,表示$\{a_i\}$. 输出格式 输出一行,两个自然数,表示$f(res)$.$res$. 样例 ...
- ZOJ 3349 Special Subsequence 简单DP + 线段树
同 HDU 2836 只不过改成了求最长子串. DP+线段树单点修改+区间查最值. #include <cstdio> #include <cstring> #include ...
- hdu 3016 dp+线段树
Man Down Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java/Others) Total S ...
- cf834D(dp+线段树区间最值,区间更新)
题目链接: http://codeforces.com/contest/834/problem/D 题意: 每个数字代表一种颜色, 一个区间的美丽度为其中颜色的种数, 给出一个有 n 个元素的数组, ...
随机推荐
- 10.15 sed 命令实践
在n行前插入 [root@wen data]# sed '2i 106,dandan,CSO' person.txt101,oldboy,CEO106,dandan,CSO102,zhangyao,C ...
- SQL学习记录:函数(二)
字符串函数 1.获取字符的ASCII码 语法结构: ASCII(espression) 这里的expression是一个返回char或varchar数据类型的表达式,ASCII函数仅对表达式最左 ...
- 高并发大流量专题---5、CDN加速
高并发大流量专题---5.CDN加速 一.总结 一句话总结: CDN就是多整几台节点服务器,选距离用户最近的服务器来给用户服务,实现的话可以用阿里云.腾讯云他们提供的功能,简单方便,妈妈再也不用担心我 ...
- 单片机程序第一句ORG 0030H什么意思
ORG是伪指令,告诉 编译 器,程序从ROM的0000开始存放程序,但是AJMP MAIN是一条无条件跳转指令,也就是说,单片机上电之后首先从0000处开始执行程序,但是,AJMP直接将程序跳转到MA ...
- soj#551 loj#2833 帐篷
传送门 分析 dp[i][j]表示考虑了i行j列的方案数 我们每次考虑三种情况: 一个点自己放 两个点在同一行 两个点在同一列 代码 #include<bits/stdc++.h> usi ...
- play framework 在idea简单运行配置(mac为例)
文章目录 play 最基本的构建 在idea中配置 配置jdk相关 配置play 运行 运行 play 最基本的构建 https://blog.csdn.net/dataiyangu/article/ ...
- C#进阶系列——WebApi 路由机制剖析:你准备好了吗? 转载https://www.cnblogs.com/landeanfen/p/5501490.html
阅读目录 一.MVC和WebApi路由机制比较 1.MVC里面的路由 2.WebApi里面的路由 二.WebApi路由基础 1.默认路由 2.自定义路由 3.路由原理 三.WebApi路由过程 1.根 ...
- python让人头大的装饰器...decorator带参不带参用法和原理.,..
0. 概念什么叫装饰器,其实也可以叫做包装器.即对于一个既有的函数func(args),在调用它之前和之后,我们希望都做一些事情,把这个函数包装起来. python中的装饰器分为两类:函数装饰器和类装 ...
- python多种推导式的实现
- Html5 学习笔记 【PC固定布局】 实战7 机票预订页面
最终实际效果: HTML代码: <!DOCTYPE html> <html lang="zh-cn"> <head> <meta char ...