【CF486E】LIS of Sequence題解

來源:互聯網
上載者:User

標籤:tps   pos   strong   過程   並集   cto   字元   space   nlogn   

【CF486E】LIS of Sequence題解題目連結題意:

給你一個長度為n的序列a1,a2,...,an,你需要把這n個元素分成三類:1,2,3:

1:所有的最長上升子序列都不包含這個元素

2:有但非所有的最長上升子序列包含這個元素

3:所有的最長上升子序列都包含這個元素

輸入格式:

第一行包含一個正整數n,表示序列的長度。第二行包含n個正整數a1,a2,...,an,表示序列中的元素。

輸出格式:

一行,包含一個長度為n的、由1,2,3三種數字組成的字串,第i個數字表示ai所屬類別。

範例輸入1:
14
範例輸出1:
3
範例輸入2:
41 3 2 5
範例輸出2:
3223
範例輸入3:
41 5 2 3
範例輸出3:
3133
時空限制:

每個測試點2s,256MB

資料範圍:

1≤n≤105

1≤ai≤105

題解:

首先,O(nlogn)求LIS大家應該都會吧……這裡就不闡述了。

我們可以通過DP來算出以每個點i結尾的最長上升子序列的長度,記為length[i],把整個序列的LIS長度記為len。

然後,大家要想明白一個命題:

如果元素i可能出現在LIS中,那麼它在LIS中的位置一定剛好等於length[i]。

這個自證不難。

其次,我們可以用一個“分層數組”,其實所謂的“分層數組”就是一個二維數組,只不過我習慣把第一維叫做“層”罷了,第二維因為節省空間的,我們開一個vector。

這個“分層數組”相當重要,它是我們解決問題的核心。我們在DP時就已經算出每個元素的length[i]了,因此我們把這個元素的編號添加到層數為length[i]的vector中去,因此“分層數組”中每一層的每個點就和序列中的元素一一對應。

這就是“分層數組”的建立過程,可參見代碼注釋。

然後呢?

大家又需要想明白兩個命題:

在每一層中,隨著編號的遞增,與點對應的元素的值單調不遞增。

每一層(除第一層外)中的每個點一定在前一層中有編號小於它且序列元素值小於它的節點。

考慮我們DP的過程,我們在更新dp數組中下標為length[i]的最小值時,如果已經通過二分尋找算出該元素的length[i],元素可以更新dp[length[i]]的條件是元素的值一定不能比dp[length[i]]大,而dp[length[i]]已經通過前面的元素算出,因此在“分層數組”層數為length[i]的層中,該元素的值一定小於等於在該層中編號比它小的元素的值。

另外,我們在DP時,依據dp數組單調遞增的特性可以理解dp[length[i]-1]的值一定比a[i]小,因此在“分層數組”的前一層中,一定有編號小於它且序列元素值小於它的點,這樣保證我們在逐層往前推的時候不會出現“一對空”的情況,而是在前一層中是有一個區間(包含編號、序列元素值兩方面的限制)與之對應。這個區間中的點就是當前點在前一層中可以擴充到的節點。

大家可能有疑問:為什麼要倒著從後往前推呢?

因為倒著推能夠保證要擴充的當前點一定有LIS經過它,因此它擴充到的前一層的節點也一定有LIS經過,等到該層所有點擴充完畢後,前一層沒有被擴充到的點一定沒有LIS經過,打上“1”類標記,下次擴充就不要擴充這些點了。而其他的點都打上“2”類標記,如果只有一個“2”類標記,那麼把“2”改成“3”,說明該節點是所有LIS的必經節點。

參考代碼如下(若有不理解的參看注釋):

 1 #include<cstdio> 2 #include<cstring> 3 #include<algorithm> 4 #include<vector> 5 #define maxn 100005 6 using namespace std; 7 int n,a[maxn];//整個序列 8 int dp[maxn];//dp[i]代表當前長度為i的上升子序列末尾元素的最小值 9 int len=0;//整個序列LIS的長度10 int sign[maxn];//序列元素所屬類別11 vector<int>layer[maxn];//分層數組,一共有len層。layer[i]中的點表示這些元素:以這些元素結尾的最長上升子序列長度為i12 inline int bins(int i,int val){13     int l=0,r=layer[i].size()-1;14     while(l<r){15         int m=(l+r)>>1;16         if(a[layer[i][m]]>=val)l=m+1;17         else r=m;18     }19     return l;20 }21 int main(){22     scanf("%d",&n);23     memset(dp,0x3f,sizeof(dp));24     dp[0]=0;25     for(int i=1;i<=n;i++){26         scanf("%d",&a[i]);27         int length=lower_bound(dp,dp+n+1,a[i])-dp;//O(nlogn)求LIS28         dp[length]=min(dp[length],a[i]);29         //length表示以該元素結尾的最長上升子序列的長度30         layer[length].push_back(i);//加入到分層數組31         len=max(len,length);//更新整個序列的LIS長度32     }33     for(int i=1;i<=n;i++)sign[i]=1;//初始化全都為第1類,即任何LIS都不經過它們34     if(layer[len].size()==1)sign[layer[len][0]]=3;35     else for(int i=0;i<layer[len].size();i++)sign[layer[len][i]]=2;36     for(int i=len;i>=2;i--){//倒序處理分層數組,一層一層往前推37         for(int j=0;j<layer[i].size();j++){//枚舉當前層的所有點38             int bh=layer[i][j];//點的編號39             if(sign[bh]>1){//如果當前節點可以向前擴充(存在LIS經過當前點)40                 int l=bins(i-1,a[bh]);//二分尋找,擴充的節點在序列中的值必須小於當前節點,才能保證LIS嚴格遞增41                 int r=lower_bound(layer[i-1].begin(),layer[i-1].end(),bh)-layer[i-1].begin()-1;//二分尋找,擴充的點編號必須小於當前點編號,才能是“序列”42                 //當前點可擴充到的前一層的點的範圍是區間[l,r]43                 for(int k=l;k<=r;k++)sign[layer[i-1][k]]=2;//打上標記,該節點能夠被擴充到說明一定在整個序列中有某個LIS包含該點44             }45         }46         //當前層能夠擴充到的前一層的點是當前層所有點能擴充到的前一層的節點的並集47         int cnt=0,pos=0;48         for(int j=0;j<layer[i-1].size();j++)if(sign[layer[i-1][j]]==2){49             cnt++;50             pos=j;51         }52         if(cnt==1)sign[layer[i-1][pos]]=3;//如果該層所有可擴充的點只能在前一層中擴充出一個節點,說明這個節點是所有LIS的必經節點。53     }54     for(int i=1;i<=n;i++)printf("%d",sign[i]);//不留空格列印55     return 0;56 }

【CF486E】LIS of Sequence題解

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.