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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

LOJ.6435.[PKUSC2018]星际穿越(倍增)

發布時間:2023/12/1 编程问答 32 豆豆
生活随笔 收集整理的這篇文章主要介紹了 LOJ.6435.[PKUSC2018]星际穿越(倍增) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

LOJ
BZOJ


參考這兒qwq。

首先詢問都是求,向左走的最短路。
\(f[i][j]\)表示從\(i\)走到\(j\)最少需要多少步。表示這樣只會\(O(n^2\log n)\)的= =但是感覺能卡過\(70\)分。

注意到從\(i\)出發,走\(j\)步能到達的點都是一段一段的。所以不妨令\(f[i][j]\)表示,從\(i\)出發,走\(j\)步能到達的最左邊的是什么。那么\(f[i][j+1]=\min\limits_{k=f[i][j]}^{i-1}L[k]\)
但是我們還沒有考慮向右走的情況。可以發現一條路徑最多只會向右走一次。
那么判一下就好惹。這樣就可以\(O(n^2)\)啦。

注意到這一過程實際可以倍增:\(f[i][j]\)表示,從\(i\)出發,走\(2^j\)步最左可以到哪。但是還要考慮第一步向右走的情況,所以不妨直接令它表示,\(i\sim n\)這些點走\(2^j\)步最左可以到哪。
\(Calc(i,p)\)表示,從\(i\)分別走到\(p\sim i\)所有點總共需要走多遠。把詢問\([l,r]\)拆成\(Calc(i,l)-Calc(i,r+1)\)
那么再維護一個\(sum[i][j]\)表示,從\(i\)出發,分別走到\(f[i][j]\sim i\)總共需要走多遠。那么\(sum[i][j]=sum[i][j-1]+sum[f[i][j-1]][j-1]+(f[i][j]-f[i][j-1])\times2^{j-1}\)

具體\(Calc\)的時候,關于向右走一步的處理,不妨直接讓\(i\)先向左走一步走到\(L[i]\)。這樣\(L[i]\)左邊的部分都有可能需要\(i\)向右走,但是這正好符合\(f\)的定義,同時我們已經跳了一步也可以看作向右跳了一步。
注意維護一個變量\(tot\)表示之前一共跳過了多少距離。

還有主席樹的做法,我不寫惹qwq 懶。


//3272ms 68628K / 69284kb 8496ms #include <cstdio> #include <cctype> #include <algorithm> #define BIT 18 #define gc() getchar() #define MAXIN 500000 //#define gc() (SS==TT&&(TT=(SS=IN)+fread(IN,1,MAXIN,stdin),SS==TT)?EOF:*SS++) typedef long long LL; const int N=3e5+5;int L[N],f[BIT+1][N]; LL sum[BIT+1][N]; char IN[MAXIN],*SS=IN,*TT=IN;inline int read() {int now=0;register char c=gc();for(;!isdigit(c);c=gc());for(;isdigit(c);now=now*10+c-48,c=gc());return now; } int Gcd(int a,int b) {return b?Gcd(b,a%b):a; } LL Calc(int l,int p,const int bit) {if(L[p]<=l) return p-l;LL ans=p-L[p],tot=1; p=L[p];for(int i=bit; ~i; --i)if(f[i][p]>=l) ans+=sum[i][p]+(p-f[i][p])*tot, tot+=1<<i, p=f[i][p];return ans+(p-l)*(tot+1);//(r-l)*tot+r-l }int main() {const int n=read(); int bit=23;while(1<<bit>n) --bit;for(int i=2; i<=n; ++i) L[i]=read();f[0][n]=L[n];for(int i=n-1; i; --i) f[0][i]=std::min(f[0][i+1],L[i]), sum[0][i]=i-f[0][i];for(int j=1; j<=bit; ++j){LL t=1ll<<j-1;for(int i=1; i<=n; ++i)f[j][i]=f[j-1][f[j-1][i]], sum[j][i]=sum[j-1][i]+sum[j-1][f[j-1][i]]+(f[j-1][i]-f[j][i])*t;}for(int Q=read(); Q--; ){int l=read(),r=read(),x=read(),b=r-l+1;LL a=Calc(l,x,bit)-Calc(r+1,x,bit); int g=Gcd(b,a%b);printf("%lld/%d\n",a/g,b/g);}return 0; }

轉載于:https://www.cnblogs.com/SovietPower/p/10734771.html

總結

以上是生活随笔為你收集整理的LOJ.6435.[PKUSC2018]星际穿越(倍增)的全部內容,希望文章能夠幫你解決所遇到的問題。

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