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

歡迎訪問 生活随笔!

生活随笔

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

编程问答

牛客 - Sixth Sense(贪心+二分)

發布時間:2024/4/11 编程问答 27 豆豆
生活随笔 收集整理的這篇文章主要介紹了 牛客 - Sixth Sense(贪心+二分) 小編覺得挺不錯的,現在分享給大家,幫大家做個參考.

題目鏈接:點擊查看

題目大意:給出兩個長度為 n 的數列記為 a 和 b,現在 a 的數列固定不動,問如何對數列 b 進行排列,可以使得:

  • b[ i ] > a[ i ] (嚴格大于)的位置盡可能多
  • 在滿足上述要求的前提下,b 的排列字典序最大
  • 題目分析:如果不考慮第二個約束的話,那就是一個非常簡單的貪心問題了,貪心策略如下:因為最終需要的是 a 中的每個元素和 b 中每個元素一一對應的一個結果,所以只需要考慮其相對位置,將兩個數組分別排序,然后用雙指針一個去枚舉 a 中的元素,另一個貪心從 b 中尋找元素與其匹配即可

    如果再考慮上第二個約束該如何去做呢,因為 n 只有 5e3 的級別,可以考慮正向遍歷一遍每個元素去確定 ans[ i ] 的值,此時不難想到一個 n^3 的做法了:

  • 首先求出不受約束 2 限制的答案,記為 res
  • 第一層枚舉 i ,表示當前正在確定 ans[ i ] 的值
  • 第二層枚舉 j ,表示第 i 個位置放置 b 中的第 j 個元素?,即 ans[ i ] = b[ j ]
  • 最后一層循環去檢查第 ans[ i ] = b[ j ] 時的答案,最后從貢獻為 res 的 b[ j ] 中選出最大的 b[ j ] 放在 ans[ i ] 即可
  • 考慮優化時間復雜度,第一層枚舉的 i 無法優化,第三層檢查的循環也不好優化,所以突破點就在第二層枚舉的 j,我們先暫時擱置一下

    到這里可能會有疑惑了,因為最開始說的,貪心策略去求解答案的話,是需要進行排序的,所以上述算法的時間復雜度不應該是 n^3*logn 的嘛,其實并不需要每次都排序,只需要初始時額外維護一個遞增的數組 aa 和數組 bb,每次操作完位置 i 后將 a[ i ] 和 b[ j ] 中相應的元素刪除掉即可,時間復雜度不過也才 O( n ) ,這樣就將每次貪心求解答案的時間控制在了 O( n )

    繼續討論如何優化掉第二層的 j,假設第一層枚舉到了 i,此時 a 數組中對應的元素是 a[ i ] ,將 bb 數組(有序)中的元素分成兩部分:

  • 小于等于 a[ i ] 的
  • 大于 a[ i ] 的
  • 不難看出兩個部分中的 bb 元素分別都是具有單調性的,具體指的是,對于情況一來說,如果 bb[ i ] 放在這里合適,那么 bb[ i + 1 ] 放在這里也是合適的,對于情況二來說,如果 bb[ i ] 放在這里合適,那么 bb[ i - 1 ] 放在這里也是合適的,如此就可以將枚舉的時間復雜度優化成二分了,最后總的時間復雜度為O( n^2logn )

    代碼:
    ?

    //#pragma GCC optimize(2) //#pragma GCC optimize("Ofast","inline","-ffast-math") //#pragma GCC target("avx,sse2,sse3,sse4,mmx") #include<iostream> #include<cstdio> #include<string> #include<ctime> #include<cmath> #include<cstring> #include<algorithm> #include<stack> #include<climits> #include<queue> #include<map> #include<set> #include<sstream> #include<cassert> #include<bitset> #include<list> #include<unordered_map> using namespace std;typedef long long LL;typedef unsigned long long ull;const int inf=0x3f3f3f3f;const int N=5e3+100;int a[N],b[N],n;vector<int>bb,aa;int cal(int ban1,int ban2)//去掉aa[ban1]和bb[ban2]后的結果 {int ans=0;int i=0,j=0;while(i<aa.size()&&j<bb.size()){if(i==ban1){i++;continue;//檢查一下是否越界 }if(j==ban2){j++;continue;//同上 }if(aa[i]<bb[j]){ans++;i++;}j++;}return ans; }int main() { #ifndef ONLINE_JUDGE // freopen("data.in.txt","r",stdin); // freopen("data.out.txt","w",stdout); #endif // ios::sync_with_stdio(false);scanf("%d",&n);for(int i=1;i<=n;i++){scanf("%d",a+i);aa.push_back(a[i]);}for(int i=1;i<=n;i++){scanf("%d",b+i);bb.push_back(b[i]);}sort(aa.begin(),aa.end());sort(bb.begin(),bb.end());int ans=cal(-1,-1);for(int i=1;i<=n;i++){int pos1=-1;//定位,aa[pos1]=a[i]for(int j=0;j<aa.size();j++)if(aa[j]==a[i])pos1=j;int l=upper_bound(bb.begin(),bb.end(),a[i])-bb.begin(),r=bb.size()-1,mark=-1;while(l<=r){int mid=l+r>>1;if(cal(pos1,mid)==ans-1){mark=mid;l=mid+1;}elser=mid-1;}if(mark==-1){int l=0,r=upper_bound(bb.begin(),bb.end(),a[i])-bb.begin()-1;while(l<=r){int mid=l+r>>1;if(cal(pos1,mid)==ans){mark=mid;l=mid+1;}elser=mid-1;}}printf("%d ",bb[mark]);ans-=(bb[mark]>aa[pos1]);aa.erase(aa.begin()+pos1);bb.erase(bb.begin()+mark);}return 0; }

    ?

    總結

    以上是生活随笔為你收集整理的牛客 - Sixth Sense(贪心+二分)的全部內容,希望文章能夠幫你解決所遇到的問題。

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