Portal --> broken qwq

Description

  大M正在学习函数的光滑性并对Lipschitz常数非常感兴趣:当一个定义域为\([l,r]\)的函数\(f\),对于定义域内的任意\(x,y\)都有\(|f(x)-f(y)|<=K*|x-y|\)时,则称\(K\)为该函数在\([l,r]\)上的Lipschitz常数。

​  然而大M并不满足于函数,所以他定义:对于一个序列\(v[1..n]\)的Lipschitz常数\(K\),当\(1<=x<y<=n\)且\(x,y\)均为整数时,同样满足\(|v[x]-v[y]|<=K*|x-y|\)的\(K\)的最小值

  现在给你一个长度为n的序列\(v[1..n]\)并给出\(q\)个询问,对于每对询问\([l,r]\),你需要求出\(v[l..r]\)的所有子序列\(v[x..y](l<=x<y<=r)\)的Lipschitz常数之和

​  数据范围:$n<=100000,q<=100 $

  

Solution

  这题的关键在于,要证明对于区间\([l,r]\)来说,\(K\)一定是\(max(\frac{|v[i]-v[i-1]}{|i-(i-1)|})\)

  我们可以将\(\frac{|v[x]-v[y]|}{|x-y|}\)看成一个求平均值的过程,再具体一点的话就是如果我们将\(v\)看成一个函数,这个式子其实相当于求一段区间(两个端点分别是\(x\)和\(y\))中\(|v[i]-v[i-1]|\)的平均值,那么也就是说明最大值显然应该是在区间长度为\(1\)的时候取得(否则总能通过舍掉较小的部分取得更优的结果)

  那所以我们可以直接求得\(K\)的所有可能的取值了(存在\(w\)数组中),接下来还是常用的套路,看每个取值能在哪个区间内提供贡献

  这个其实比较好处理,我们用一个单调栈预处理出每一个\(K\)值的前一个比它大的位置和后一个比它大的位置,前者记为\(pre\),后者记为\(nxt\),那么我们可以直接算出这个由\(|v[i]-v[i-1]|\)产生的\(K\)对答案的贡献了,它能贡献的子区间左端点的取值范围为\(w\)数组中的\([max(l+1,pre+1),i]\),右端点的取值范围为\(w\)数组中的\([i,min(r,nxt-1)]\),其中\(l,r\)是询问的区间

​  什么叫做\(w\)数组中的一个区间呢?其实是因为\(w\)数组的定义写出来的话应该是\(w[i]=|v[i]-v[i-1]|\),也就是说\(w\)中的一个位置其实包含了\(v\)中的两个位置,这么说好像还是有点绕,但反正就是边界什么的需要稍微。。自己推一下

​  然后还有一个问题是如果说\(w\)数组中(也就是\(K\)的所有取值中)有重复的怎么处理,那其实比较显然只要左端点算上重复的,右端点不算上就好了

​  (然而。。貌似左端点不算右端点算不太行的样子(也可能是因为我自己写挫了),就比如说会出现这种情况:\(w=\{0,2,1,2,1\}\),然后如果左端点不算右端点算的话会把\(K=2\)时的\(\{2,1,2,1\}\)这种情况漏掉)

  

​  代码大概长这个样子

#include<iostream>
#include<cstdio>
#include<cstring>
#include<queue>
#define Pr pair<int,int>
#define mp make_pair
#define ll long long
using namespace std;
const int N=100010;
int a[N],pre[N],nxt[N],loc[N],w[N];
Pr rec[N];
int n,m,top;
int Abs(int x){return x<0?-x:x;}
bool cmp(int x,int y){return w[x]<w[y];}
void prework(){
top=0;
pre[1]=0; rec[++top]=mp(w[1],1);
for (int i=2;i<=n;++i){
while(top&&rec[top].first<w[i]) --top;
if (top==0) pre[i]=0;
else pre[i]=rec[top].second;
rec[++top]=mp(w[i],i);
}
top=0;
nxt[n]=n+1; rec[++top]=mp(w[n],n);
for (int i=n-1;i>=1;--i){
while (top&&rec[top].first<w[i]) --top;
if (top==0) nxt[i]=n+1;
else nxt[i]=rec[top].second;
rec[++top]=mp(w[i],i);
}
}
void solve(int l,int r){
int L,R;
ll ans=0;
for (int i=l+1;i<=r;++i){
L=max(l+1,w[pre[i]]==w[i]?pre[i]:pre[i]+1),R=min(nxt[i]-1,r);
ans+=1LL*w[i]*((R-i+1)*(i-L+1));
//printf("%d %d\n",w[i],(R-i+1)*(i-L+1));
}
printf("%lld\n",ans);
} int main(){
#ifndef ONLINE_JUDGE
freopen("a.in","r",stdin);
#endif
int l,r;
scanf("%d%d",&n,&m);
for (int i=1;i<=n;++i) scanf("%d",a+i);
w[1]=0;
for (int i=2;i<=n;++i) w[i]=Abs(a[i]-a[i-1]);
prework();
for (int i=1;i<=m;++i){
scanf("%d%d",&l,&r);
solve(l,r);
}
}
/*
input1
10 4
1 5 2 9 1 3 4 2 1 7
2 4
3 8
7 10
1 9 output1
17
82
23
210 input2
7 6
5 7 7 4 6 6 2
1 2
2 3
2 6
1 7
4 7
3 5 output2
2
0
22
59
16
8
*/

Lipshitz的更多相关文章

  1. Codeforces Round #333 (Div. 1) B. Lipshitz Sequence 倍增 二分

    B. Lipshitz Sequence Time Limit: 20 Sec Memory Limit: 256 MB 题目连接 http://codeforces.com/contest/601/ ...

  2. [Contest20171109]函数(lipshitz)

    大M正在学习函数的光滑性并对Lipshitz常数非常感兴趣:当一个定义域为$[l,r]$的函数$f$,对于定义域内的任意$x,y$都有$\left|f(x)-f(y)\right|\leq K\cdo ...

  3. CodeForces 601B Lipshitz Sequence

    Lipshitz Sequence 题解: 可以通过观察得到,对于任意一个区间来说, 只有相邻的2个点的差值才会是区间的最大值. 具体观察方法,可以用数学分析, 我是通过画图得到的. 那么基于上面的观 ...

  4. Codeforces 601B. Lipshitz Sequence(单调栈)

    Codeforces 601B. Lipshitz Sequence 题意:,q个询问,每次询问给出l,r,求a数组[l,r]中所有子区间的L值的和. 思路:首先要观察到,斜率最大值只会出现在相邻两点 ...

  5. Codeforces Round #333 (Div. 1)--B. Lipshitz Sequence 单调栈

    题意:n个点, 坐标已知,其中横坐标为为1~n. 求区间[l, r] 的所有子区间内斜率最大值的和. 首先要知道,[l, r]区间内最大的斜率必然是相邻的两个点构成的. 然后问题就变成了求区间[l, ...

  6. CF 602 D. Lipshitz Sequence 数学 + 单调栈 + 优化

    http://codeforces.com/contest/602/problem/D 这题需要注意到的是,对于三个点(x1, y1)和(x2, y2)和(x3, y3).如果要算出区间[1, 3]的 ...

  7. 【codeforces 602D】Lipshitz Sequence

    time limit per test1 second memory limit per test256 megabytes inputstandard input outputstandard ou ...

  8. Codeforces Round #333 (Div. 2)

    水 A - Two Bases 水题,但是pow的精度不高,应该是转换成long long精度丢失了干脆直接double就可以了.被hack掉了.用long long能存的下 #include < ...

  9. Codeforces Round #333 DIV2

    D: B. Lipshitz Sequence time limit per test 1 second memory limit per test 256 megabytes input stand ...

随机推荐

  1. Jmeter使用HTTP代理服务器录制脚本

    使用Jmeter录制脚本通常使用Badboy工具录制或者Jmeter自带的HTTP代理服务器录制脚本,这里说一下使用HTTP代理服务器录制时遇到的问题. 1.  Jmeter安装 下载得到Jmeter ...

  2. 8 个用于业余项目的优秀 Python 库

    在 Python/Django 的世界里有这样一个谚语:为语言而来,为社区而留.对绝大多数人来说的确是这样的,但是,还有一件事情使得我们一直停留在 Python 的世界里,不愿离开,那就是我们可以很容 ...

  3. 从零开始的Python学习Episode 8——深浅拷贝

    深浅拷贝 一.浅拷贝 列表中存储的是数据的内存地址,当我们要查询或修改列表中的数据时,我们是通过列表中的地址找到要访问的内存.当我们修改列表中的数据时,如果修改的是一个不可变类型(整型,长整型,浮点数 ...

  4. curl和file_get_contents 区别以及各自的优劣

    PHP中fopen,file_get_contents,curl函数的区别: 1.fopen /file_get_contents 每次请求都会重新做DNS查询,并不对 DNS信息进行缓存.但是CUR ...

  5. DoItYourself!

    在杨老师的勉励下,我准备开始“自己”写程序.速度很慢,不过在写的过程中对于用到的几个函数更加熟悉.也尝试多学一点,学透一点.遇到不会的函数,语法不清楚的,还是会百度,不过会自己再敲一遍.重复下去. 下 ...

  6. listagg wm_concat 行转列

    一. 这个写法和wm_concat相似,listagg(day,',')要把哪一列转换为同一行within group (order by day)同一行如何排序 with temp as ( ' d ...

  7. Java JDK安装及环境配置

    转载:https://jingyan.baidu.com/article/6dad5075d1dc40a123e36ea3.html 环境变量配置: 系统变量→新建 JAVA_HOME 变量 . 变量 ...

  8. Linux 环境下svn 服务器搭建

    可使用自己下载的svn安装包,但要安装相关依赖包,yum 安装源提供的稳定版本svn 1.yum -y install subversion 2.创建本地库 mkdir -p /var/svn svn ...

  9. spring-test与junit

    1.添加依赖 spring-test junit spring-context(自动添加依赖其他所需的spring依赖包) 2.在class前添加以下注解,用于配置xml文件的位置 @RunWith( ...

  10. 1014 我的C语言文法定义与C程序推导过程

    程序> -> <外部声明> | <程序> <外部声明> <外部声明> -> <函数定义> | <声明> < ...