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

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程资源 > 编程问答 >内容正文

编程问答

CometOJ #10 沉鱼落雁 | 思维

發(fā)布時(shí)間:2023/12/14 编程问答 33 豆豆
生活随笔 收集整理的這篇文章主要介紹了 CometOJ #10 沉鱼落雁 | 思维 小編覺得挺不錯(cuò)的,現(xiàn)在分享給大家,幫大家做個(gè)參考.

題意:給你n個(gè)數(shù)字,其中有的數(shù)字會(huì)重復(fù)出現(xiàn)(但最多出現(xiàn)3次),問你如何安排這些數(shù)字,可以使得相同數(shù)字之間的最小間隔最大。不需要打印具體的安排策略,只要求出最大的最小間隔即可。

這里首先要搞明白,最小間隔指的是什么。比如說3 4 5 3 6 3 4,這里的最小間隔就是1(題目規(guī)定間隔為j - i - 1),3的間隔有2,1兩種,4的講個(gè)是4 。但是要求的是最小間隔,所以取這些間隔中的最小值2 。

經(jīng)過思考不難發(fā)現(xiàn),因?yàn)樽疃喑霈F(xiàn)3次,那么假如有出現(xiàn)3次的數(shù)字,我們肯定是順著排,比如說1 1 2 1 2 2 這個(gè),我們排好一定是1 2 1 2 1 2,如果是三組或者更多出現(xiàn)三次的數(shù)字效果也是一樣的。出現(xiàn)三次的數(shù)字在這樣排布之后,一共有三部分,每部分的數(shù)字不同。這三部分形成了兩個(gè)間隔,那么,不難想到,假如我們要求最小間隔最大,那么如果有二次出現(xiàn)的數(shù)字,一定是均勻分開,填充到這兩個(gè)間隔中取。對于出現(xiàn)1次的數(shù)字,一次放到間隔I,一次放到間隔II,重復(fù)這個(gè)過程。也就是說,出現(xiàn)1次的數(shù)字,只有有偶數(shù)個(gè)的時(shí)候才會(huì)增加最小間隔。

如果沒有出現(xiàn)3次的數(shù)字呢?對于多組出現(xiàn)2次的數(shù)字,我們的策略跟上面出現(xiàn)3次的是一樣的。分成兩部分,每部分?jǐn)?shù)字不同。假如有出現(xiàn)1次的數(shù)字,就往這兩部分形成的間隙中填充。這里與三次的間隙不同,1次數(shù)字不論奇偶,放進(jìn)去多少個(gè),間隔就增加多少。

分析完之后,我們解決問題的關(guān)鍵就變成了:如何統(tǒng)計(jì)出現(xiàn)3次、2次、1次數(shù)字的數(shù)量?

這里也是我當(dāng)時(shí)一直卡住的點(diǎn)。我想用類似桶排的思想,數(shù)組的標(biāo)號(hào)表示數(shù)字的值,但是,因?yàn)閿?shù)字的范圍是1e9所以必然會(huì)超。之后又想到,因?yàn)榭倐€(gè)數(shù)是1e5,事前又不能確定n的大小,可以采用向量。
但是我讀完放入向量之后,先進(jìn)行sort排序,然后再用count來查詢在整個(gè)vector中出現(xiàn)的次數(shù)。其實(shí)如果要用count,就沒必要sort,sort之后完全可以回到下面AC代碼中的判斷方法。count,復(fù)雜度是O(n),加上前面的部分,所以TLE 。

今天補(bǔ)題的時(shí)候看到別人的方法,感覺自己真的蠢……統(tǒng)計(jì)出現(xiàn)的次數(shù),sort之后相同元素都會(huì)在一起,我們記錄不同元素下標(biāo)之間的差,其實(shí)就是前一元素的數(shù)目,那只要O(n)掃一遍即可。

其實(shí)昨晚我最后的vector方法已經(jīng)非常接近……也使用了記錄上一不同值及其下標(biāo)進(jìn)行計(jì)算的方法,但是明明已經(jīng)sort了還要用count查詢,就很蠢……應(yīng)該就是n次計(jì)算,每次都調(diào)用count導(dǎo)致了TLE。

最后還有一個(gè)坑。就是用數(shù)組統(tǒng)計(jì)個(gè)數(shù)的時(shí)候,究竟怎么計(jì)算的問題。我的lastmark記錄的是最新不同元素的第一個(gè)的下標(biāo),一旦不同,進(jìn)入這個(gè)分支我們cnt[__] 中 __ 統(tǒng)計(jì)的不是當(dāng)前元素是3次2次還是1次,而是上一元素的,所以不需要+1(因?yàn)槲覀儺?dāng)前的坐標(biāo)i本身就是新元素的第一個(gè)而不是上一元素的最后一個(gè))。
還有就是對于最后一個(gè)位置,是很特殊的,因?yàn)槲覀兊絥-1就跳出,所以最后一次可能會(huì)來不及更新。最后一個(gè)位置有兩種情況,一種是,最后一個(gè)元素它只出現(xiàn)了一次,那么就直接cnt[1]++即可;另一種情況是它出現(xiàn)了多次,但是這里要注意:我們此時(shí)i表示的是當(dāng)前元素的最后一個(gè)的下標(biāo),而不同于上面對1~n-1的元素處理時(shí)表示新元素的第一個(gè),所以這里要+1才是正確的!(因?yàn)檫@里WA了好久……想破頭才發(fā)現(xiàn)是這里錯(cuò)了(。

#include <bits/stdc++.h>using namespace std;int n, ans; int cntset[4];int main() {scanf("%d", &n);const int size_ = n;int numset[size_];memset(numset, 0, sizeof(numset));//0 - n-1讀入n個(gè)數(shù)字for(int i = 0;i < n;i++)scanf("%d", &numset[i]);sort(numset, numset+size_);//排序int lastcon = -1, //上一次記錄的成語lastmark = 0; //第一個(gè)不同數(shù)字出現(xiàn)的位置for(int i = 0;i < n;i++){//printf("numset[%d] = %d\n", i, numset[i]);if(numset[i] != lastcon){cntset[i-lastmark]++;//實(shí)際統(tǒng)計(jì)的不是當(dāng)前的數(shù)字,而是上一個(gè)lastcon = numset[i];//當(dāng)前數(shù)字是新一種數(shù)字的第一個(gè)lastmark = i;}if(i == n-1)//最后一個(gè)元素{if(lastmark == i)cntset[1]++;else//前面還有cntset[i-lastmark+1]++;}}if(cntset[3])//均只出現(xiàn)一次ans = cntset[3]-1+cntset[2]+cntset[1]/2;else if(cntset[2])//只有2 1ans = cntset[2]-1+cntset[1];elseans = n;printf("%d\n", ans);return 0; }

總結(jié)

以上是生活随笔為你收集整理的CometOJ #10 沉鱼落雁 | 思维的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯(cuò),歡迎將生活随笔推薦給好友。