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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

CodeForces 359D (数论+二分+ST算法)

發布時間:2023/12/31 编程问答 28 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CodeForces 359D (数论+二分+ST算法) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接: http://acm.hust.edu.cn/vjudge/problem/viewProblem.action?id=47319

題目大意:給定一個序列,要求確定一個子序列,①使得該子序列中所有值都能被其中一個值整除,②且子序列范圍盡可能大(r-l盡可能大)。

解題思路

對于要求1,不難發現只有min(L,R)=gcd(L,R)時才行。其中gcd是L,R范圍內的最大公約數,min是L,R范圍內的最小值。

對于要求2,傳統思路是r-l從大到小枚舉,每次確定一個(L,R)范圍,進行判斷,直到可行。復雜度O(n^2)鐵定TLE。

由于r-l的值是有序的,固采用二分。先枚舉r-l的中間值,如果符合要求,則向右考慮,看看有沒有更大的。否則向左。

當然這題的難度不止于此,盡管采用二分,但是光是枚舉復雜度就有O(nlogn)了,再加上查詢orz。

最初我使用的是線段樹完成RMQ、以及GCD的Query , 復雜度O(n*logn*logn), CF跑到Test10就TLE了。

看了題解才發現要使用ST算法在O(1)的時間內完成RMQ和GCD。也是第一次碰到ST算法,看見劉汝佳的炒雞簡潔ST,給跪了。

?

#include "cstdio" #include "iostream" #include "vector" #include "algorithm" #include "math.h" #include "cstring" using namespace std; #define lson l,mid,root<<1 #define rson mid+1,r,root<<1|1 #define maxn 3*100005 #define maxp 20 template <class T> inline bool read(T &ret) {char c;int sgn;if(c=getchar(),c==EOF) return 0; //EOFwhile(c!='-'&&(c<'0'||c>'9')) c=getchar();sgn=(c=='-')?-1:1;ret=(c=='-')?0:(c-'0');while(c=getchar(),c>='0'&&c<='9') ret=ret*10+(c-'0');ret*=sgn;return 1; } int gcd(int a,int b) {if(b!=0) return gcd(b,a%b);else return a;} int RMQ[maxn][maxp],GCD[maxn][maxp],val[maxn],n,cnt,range; vector<int> ans; void ST() {for(int i=1;i<=n;i++) RMQ[i][0]=GCD[i][0]=val[i];for(int j=1;(1<<j)<=n;j++)for(int i=1;i+(1<<j)-1<=n;i++){RMQ[i][j]=min(RMQ[i][j-1],RMQ[i+(1<<(j-1))][j-1]);GCD[i][j]=gcd(GCD[i][j-1],GCD[i+(1<<(j-1))][j-1]);} } bool Query(int L,int R) {int k=0;while((1<<(k+1))<=R-L+1) k++;int a=min(RMQ[L][k],RMQ[R-(1<<k)+1][k]);int b=gcd(GCD[L][k],GCD[R-(1<<k)+1][k]);if(a==b) return true;else return false; } bool judge(int v) //枚舉r-l {int cc=0;vector<int> tt;for(int i=1; v+i<=n; i++){if(Query(i,i+v)) //L=i,R=i+v; {cc++;tt.push_back(i);}}if(cc>0){ans=tt;cnt=cc;range=v;return true;}return false; } int main() {memset(RMQ,1,sizeof(RMQ));memset(GCD,1,sizeof(GCD));read(n);for(int i=1; i<=n; i++)read(val[i]);ST();int l=0,r=n-1,mid;while(l<=r) //二分 {mid=(l+r)>>1;if(judge(mid)) l=mid+1;else r=mid-1;}printf("%d %d\n",cnt,range);for(int i=0;i<ans.size();i++) {if(i>0) printf(" ");printf("%d",ans[i]);};printf("\n"); }

?

2808371neopenxCodeForces 359DAccepted51924 KB358 msGNU C++ 4.61981 B2014-10-03 15:00:32

?

???

?

總結

以上是生活随笔為你收集整理的CodeForces 359D (数论+二分+ST算法)的全部內容,希望文章能夠幫你解決所遇到的問題。

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