牛客 字典序 思維

2021-10-06 16:42:46 字數 1341 閱讀 6148

題目大意:給出乙個長度為 n 的數列 a ,構造 s[ i ] 是數列 a 去掉 a[ i ] 後的數列,現在需要對 s 排序,輸出排序後的結果

題目分析:一提到排序,可以試著寫一下 sort 的 cmp ,然後剩下的就不用我們操心了

對於 cmp 函式,我們的目標是給出兩個位置 x 和 y ,從而確定其相應的大小

首先假設 x < y ,這個時候,數列 s[ x ] 和 數列 s[ y ] 的長度肯定是相等的

如上圖所示,我們可以將整個數列分為三段,其中對於第一段和第三段而言,s[ x ] 和 s[ y ] 是完全相同的,只有在第二段中,這 y - x 個數是交叉對應的,我們為了比較兩個數列的大小,只需要找到位置 x 後的首個位置 pos ,滿足 a[ pos ] != a[ pos + 1 ] ,這個時候判斷一下這兩個數的大小就能比較出兩個數列的大小了,這裡需要注意的點是,pos 需要滿足在區間 [ x , y ) 才行,如果 pos 不在這個區間內的話,就說明 s[ x ] 和 s[ y ] 的第二段是相等的,綜上得出 s[ x ] 和 s[ y ] 是相等的

接下來考慮 x > y 的情況,其實就是上面把 x 和 y 的位置換一下,思路完全一樣

最後的問題就是,如何快速找到這個位置 pos 呢,我採取的乙個方法就是,預處理把 a[ i ] != a[ i + 1 ] 的所有 i 都放到乙個 vector 裡,然後就可以二分查詢了,這樣總的時間複雜度是 nlognlogn,對於 n = 1e5 的資料還是綽綽有餘的

**:

#include#include#include#include#include#include#include#include#include#include#include#include#include#include#includeusing namespace std;

typedef long long ll;

typedef unsigned long long ull;

const int inf=0x3f3f3f3f;

const int n=1e6+100;

int a[n],ans[n];

vectorpos;

int main()

for(int i=1;ia[pos[j]];

}return x

});printf("%d",ans[1]);

for(int i=2;i<=n;i++)

printf(" %d",ans[i]);

puts("");

} return 0;

}

牛客,String of CCPC(思維)

題意 給定乙個長度為n的字串s n s n 只由c,p組成,定義s n 的價值為 s n 中不同的 ccpc 連續子串的個數。現可以向這個子串中插入乙個c,p,但第i次操作,需要消耗i 1的單位價值。求s n 的價值最大為多少。分析 稍微分析一下,可以發現,每次操作,最多只能使s n 的價值 1,假...

牛客 Shortest Path dfs 思維

非常巧妙的轉換。首先我們可以觀察性質,一條邊不可能出現兩次,因為顯然可以被更好的方案替代 之後,每個邊就存在選或者不選兩種情況 如果以子樹的節點為偶數,那麼就不需要,否則需要,做一下dfs即可 includeusing namespace std typedef long long ll const...

牛客練習賽16 A 字典序最大的子串行 思維

思路就是既然要找字典序最大的子串行,那就是將最大的先存起來,然後我們如果直接去找最大的字元不好確定它的位置,所以我們需要反著去找,因為最後乙個字元肯定是要存起來的,然後再從後往前遍歷,將大於等於前乙個字元的都存起來就好了。ac include include include include incl...