日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

Lipshitz

發布時間:2023/12/18 编程问答 29 豆豆
生活随笔 收集整理的這篇文章主要介紹了 Lipshitz 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

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_JUDGEfreopen("a.in","r",stdin); #endifint 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 9output1 17 82 23 210input2 7 6 5 7 7 4 6 6 2 1 2 2 3 2 6 1 7 4 7 3 5output2 2 0 22 59 16 8 */

轉載于:https://www.cnblogs.com/yoyoball/p/9383205.html

總結

以上是生活随笔為你收集整理的Lipshitz的全部內容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網站內容還不錯,歡迎將生活随笔推薦給好友。