CF1479B Painting the Array(貪心+DP)

題目大意:給你一個序列,讓你提取出一個子序列A,剩餘的部分組成子序列B,現定義seg(x)表示把序列x中相鄰的相同數合併成一個數後,序列x的長度,分別求seg(A)+seg(B)的最大值和最小值,n=1e5

考場上並沒有想出最小值做法,只會最大值的貪心,下考才知道可以DP做??

 

最大值的貪心:

維護$nxt[i]$表示$a[i]$下一次出現的位置。再模擬構造兩個序列的過程,新加進來的數放在序列尾元素的$nxt$較小的序列

 1 #include <cmath>
 2 #include <queue>
 3 #include <vector>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <algorithm>
 7 #define ll long long
 8 #define ull unsigned long long 
 9 #define dd double
10 using namespace std;
11 const int N1=105; const ll inf=0x3f3f3f3f3f3f3f3fll;
12 
13 int n;
14 int a[N1],b[N1],c[N1],nxt[N1],la[N1],cntb,cntc;
15 
16 int main()
17 {
18     scanf("%d",&n);
19     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
20     int i,j,ans=0;
21     for(i=n;i>=1;i--) 
22     {
23         if(!la[a[i]]) la[a[i]]=i, nxt[i]=n+1;
24         else nxt[i]=la[a[i]], la[a[i]]=i;
25     }
26     nxt[0]=n+1;
27     for(i=1;i<=n;i++)
28     {
29         if(a[i]==a[b[cntb]]&&a[i]==a[c[cntc]]){
30             if(b[cntb]>c[cntc]) c[cntc]=i;
31             else b[cntb]=i;
32         }else if(a[i]==a[b[cntb]]){
33             c[++cntc]=i;
34         }else if(a[i]==a[c[cntc]]){
35             b[++cntb]=i;
36         }else{
37             if(a[b[cntb]]==a[c[cntc]]){
38                 if(b[cntb]>c[cntc]) c[++cntc]=i; //改小的
39                 else b[++cntb]=i;
40             }else{
41                 if(nxt[b[cntb]]<=nxt[c[cntc]]) b[++cntb]=i;
42                 else c[++cntc]=i;
43             }
44         }
45     }
46     printf("%d\n",cntb+cntc);
47     return 0;
48 }
View Code

 

最小值的DP:

首先一步貪心,把相鄰的相同元素都合併,這樣新的序列裏一定沒有相同的相鄰元素

題目裏把序列劃分成$01$序列,我們$DP$每個01or10分界點!

維護$f[i][0/1]$表示第$i$個元素放在$0/1$,第$i-1$個元素放在$1/0$時的答案

也就是$j~i-1$的元素放在一個序列裏,再把$i$接在$j-1$所在序列的後面

可得方程$f[i][0/1]=f[j][1/0]+i-j-(a[i]=a[j-1])$

利用前綴和優化成$O(n)$

 1 #include <cmath>
 2 #include <queue>
 3 #include <vector>
 4 #include <cstdio>
 5 #include <cstring>
 6 #include <algorithm>
 7 #define ll long long
 8 #define ull unsigned long long 
 9 #define dd double
10 using namespace std;
11 const int N1=100005; const int inf=0x3f3f3f3f;
12 
13 int n,nn;
14 int a[N1],b[N1],f[N1][2],mval[N1][2];
15 
16 int main()
17 {
18     scanf("%d",&nn);
19     for(int i=1;i<=nn;i++) scanf("%d",&b[i]);
20     for(int i=1;i<=nn;i++) if(b[i]!=b[i-1]) a[++n]=b[i];
21     memset(mval,0x3f,sizeof(mval)); a[0]=-1;
22     // mi[1][0]=f[1][0]=1; 
23     f[1][0]=1; f[1][1]=inf;
24     int mf[2]={0,inf};
25     for(int i=2;i<=n;i++)
26     {
27         f[i][0]=min(mval[a[i]][1]+i-1,mf[1]+i);
28         f[i][1]=min(mval[a[i]][0]+i-1,mf[0]+i);
29         mf[0]=min(f[i][0]-i,mf[0]); mf[1]=min(f[i][1]-i,mf[1]);
30         mval[a[i-1]][0]=min(mval[a[i-1]][0],f[i][0]-i); 
31         mval[a[i-1]][1]=min(mval[a[i-1]][1],f[i][1]-i); 
32     }
33     printf("%d\n",min(f[n][0],f[n][1]));
34     return 0;
35 }
View Code

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章