zoukankan      html  css  js  c++  java
  • 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
    ",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
    ",min(f[n][0],f[n][1]));
    34     return 0;
    35 }
    View Code
  • 相关阅读:
    团队项目——需求规格说明书
    UML
    第二次团队作业——预则立&&他山之石
    团队选题报告
    团队展示
    ubuntu下使用pyinstaller将python文件打包成exe(py文件中含有keras框架的代码)
    ubuntu 为项目配置虚拟环境
    安装cuda9.0 + cudnn7.0 与 cuda8.0共存
    ubuntu 16.04 + cuda8.0 + cudnn 6.1 + tensorflow 1.4.0
    修改vs2013中MFC项目名称
  • 原文地址:https://www.cnblogs.com/guapisolo/p/14397487.html
Copyright © 2011-2022 走看看