Lipshitz
Portal --> broken qwq
Description
大M正在學(xué)習(xí)函數(shù)的光滑性并對(duì)Lipschitz常數(shù)非常感興趣:當(dāng)一個(gè)定義域?yàn)?span id="ozvdkddzhkzd" class="math inline">\([l,r]\)的函數(shù)\(f\),對(duì)于定義域內(nèi)的任意\(x,y\)都有\(|f(x)-f(y)|<=K*|x-y|\)時(shí),則稱\(K\)為該函數(shù)在\([l,r]\)上的Lipschitz常數(shù)。 ?
? 然而大M并不滿足于函數(shù),所以他定義:對(duì)于一個(gè)序列\(v[1..n]\)的Lipschitz常數(shù)\(K\),當(dāng)\(1<=x<y<=n\)且\(x,y\)均為整數(shù)時(shí),同樣滿足\(|v[x]-v[y]|<=K*|x-y|\)的\(K\)的最小值
現(xiàn)在給你一個(gè)長(zhǎng)度為n的序列\(v[1..n]\)并給出\(q\)個(gè)詢問(wèn),對(duì)于每對(duì)詢問(wèn)\([l,r]\),你需要求出\(v[l..r]\)的所有子序列\(v[x..y](l<=x<y<=r)\)的Lipschitz常數(shù)之和
? 數(shù)據(jù)范圍:$n<=100000,q<=100 $
Solution
這題的關(guān)鍵在于,要證明對(duì)于區(qū)間\([l,r]\)來(lái)說(shuō),\(K\)一定是\(max(\frac{|v[i]-v[i-1]}{|i-(i-1)|})\)
我們可以將\(\frac{|v[x]-v[y]|}{|x-y|}\)看成一個(gè)求平均值的過(guò)程,再具體一點(diǎn)的話就是如果我們將\(v\)看成一個(gè)函數(shù),這個(gè)式子其實(shí)相當(dāng)于求一段區(qū)間(兩個(gè)端點(diǎn)分別是\(x\)和\(y\))中\(|v[i]-v[i-1]|\)的平均值,那么也就是說(shuō)明最大值顯然應(yīng)該是在區(qū)間長(zhǎng)度為\(1\)的時(shí)候取得(否則總能通過(guò)舍掉較小的部分取得更優(yōu)的結(jié)果)
那所以我們可以直接求得\(K\)的所有可能的取值了(存在\(w\)數(shù)組中),接下來(lái)還是常用的套路,看每個(gè)取值能在哪個(gè)區(qū)間內(nèi)提供貢獻(xiàn)
這個(gè)其實(shí)比較好處理,我們用一個(gè)單調(diào)棧預(yù)處理出每一個(gè)\(K\)值的前一個(gè)比它大的位置和后一個(gè)比它大的位置,前者記為\(pre\),后者記為\(nxt\),那么我們可以直接算出這個(gè)由\(|v[i]-v[i-1]|\)產(chǎn)生的\(K\)對(duì)答案的貢獻(xiàn)了,它能貢獻(xiàn)的子區(qū)間左端點(diǎn)的取值范圍為\(w\)數(shù)組中的\([max(l+1,pre+1),i]\),右端點(diǎn)的取值范圍為\(w\)數(shù)組中的\([i,min(r,nxt-1)]\),其中\(l,r\)是詢問(wèn)的區(qū)間
? 什么叫做\(w\)數(shù)組中的一個(gè)區(qū)間呢?其實(shí)是因?yàn)?span id="ozvdkddzhkzd" class="math inline">\(w\)數(shù)組的定義寫出來(lái)的話應(yīng)該是\(w[i]=|v[i]-v[i-1]|\),也就是說(shuō)\(w\)中的一個(gè)位置其實(shí)包含了\(v\)中的兩個(gè)位置,這么說(shuō)好像還是有點(diǎn)繞,但反正就是邊界什么的需要稍微。。自己推一下
? 然后還有一個(gè)問(wèn)題是如果說(shuō)\(w\)數(shù)組中(也就是\(K\)的所有取值中)有重復(fù)的怎么處理,那其實(shí)比較顯然只要左端點(diǎn)算上重復(fù)的,右端點(diǎn)不算上就好了
? (然而。。貌似左端點(diǎn)不算右端點(diǎn)算不太行的樣子(也可能是因?yàn)槲易约簩懘炝?#xff09;,就比如說(shuō)會(huì)出現(xiàn)這種情況:\(w=\{0,2,1,2,1\}\),然后如果左端點(diǎn)不算右端點(diǎn)算的話會(huì)把\(K=2\)時(shí)的\(\{2,1,2,1\}\)這種情況漏掉)
? 代碼大概長(zhǎng)這個(gè)樣子
#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 */轉(zhuǎn)載于:https://www.cnblogs.com/yoyoball/p/9383205.html
總結(jié)
- 上一篇: eclipse 中 Android sd
- 下一篇: 加快上架方法