zoukankan      html  css  js  c++  java
  • CF1481X Codeforces Round #699

    C Fence Painting(构造)

    有用的刷子贪心刷,没用的刷子填在后续的有用/已存在的位置(用个栈记一下就行)

    D AB Graph(图上构造)

    把边当做三种类型,aa bb ab

    m为奇数时,随便挑一条边来回跑m次就行,一定是回文的

    m为偶数时,如果存在aa or bb边,来回跑m次;如果不存在,那么图中只有ab边。由于这是一张完全图,$nge 3$时一定存在两条连续的首尾相接的ab边,根据m/2的奇偶性即可构造出回文串

    考场后1min敲完,我真行

     1 const int N1=1005; const ll inf=0x3f3f3f3f3f3f3f3fll;
     2 
     3 int n,T,m;
     4 int p[N1][N1];
     5 char str[N1];
     6 int solve()
     7 {
     8     for(int i=1;i<=n;i++) 
     9     {
    10         scanf("%s",str+1);
    11         for(int j=1;j<=n;j++) if(j!=i)
    12             if(str[j]=='a') p[i][j]=0; else p[i][j]=1;
    13     }
    14     int fl;
    15     if(m&1){
    16         puts("YES");
    17         for(int k=0;k<=m;k++) if(k&1) printf("%d ",1); else printf("%d ",2);
    18             puts("");
    19         return 1;
    20     }else{
    21         for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j)
    22         {
    23             if(p[i][j]==p[j][i])
    24             {
    25         puts("YES");
    26                 for(int k=0;k<=m;k++) if(k&1) printf("%d ",i); else printf("%d ",j);
    27             puts("");
    28                 return 1;
    29             }
    30         }
    31         if(n==2) return 0;
    32         for(int i=1;i<=n;i++) for(int j=1;j<=n;j++) if(i!=j)
    33         for(int k=1;k<=n;k++) if(k!=i&&k!=j&&p[i][j]==p[j][k])
    34         {
    35             puts("YES");
    36             if((m/2)&1)
    37             {
    38                 for(int l=0;l<=m/2;l++) if(l&1) printf("%d ",j); else printf("%d ",i);
    39                 for(int l=m/2+1;l<=m;l++) if(l&1) printf("%d ",j); else printf("%d ",k);
    40             }else{
    41                 for(int l=0;l<=m/2;l++) if(l&1) printf("%d ",k); else printf("%d ",j);
    42                 for(int l=m/2+1;l<=m;l++) if(l&1) printf("%d ",i); else printf("%d ",j);
    43             }
    44             puts("");
    45             return 1;
    46         }
    47     }
    48     return 0;
    49 }
    50 
    51 int main()
    52 {
    53     freopen("a.in","r",stdin);
    54     scanf("%d",&T);
    55     while(T--)
    56     {
    57         scanf("%d%d",&n,&m);
    58         int ans=solve();
    59         if(!ans) puts("NO");
    60     }
    61     return 0;
    62 }
    View Code

    E Sorting books(DP)

    题目大意:给你一个序列,每次操作可以把一个数放到最后面,问最少需要多少次操作,能让所有相同的数连在一起。$n=5e5$

    大力$DP$就行

    设$l[i],r[i]$分别表示数i在最左和最右边出现的位置

    设$f[i]$表示$i$到$n$中的所有$l[j]ge i$的数中,可以保留的数字的最大数目,剩下的数都需要按照某种顺序移动到右面

    若$f[i]=l[a_{i}]$,如果把$a[i]$留下,那么在$l[a_{i}]$和$r[a_{i}]$之间的其它数字都不能保留,$f[i]=f[r[a_{i}]+1]+num[a_{i}]$

    如果不保留$a_{i}$,或者$f[i]$不等于$l[a_{i}]$,那么$f[i]=f[i+1]$

    最终答案是$n-f[1]$

    然而会有反例,比如2 2 1 2 2 2 1 1 3,最优方案是挪最左边的1,再把3挪到1的右边,代价为2,上面的DP求出的答案是3,即保留2和3挪1

    这时需要单独考虑挪走尾部一段数的情况

    如果$f[i]$不等于$l[a_{i}]$,例如$f[7]$,保留7和7后面的所有1也是一种可行方案!这其实是在讨论序列最后一个不动的数在哪

     1 const int N1=500005; const int inf=0x3f3f3f3f;
     2 
     3 int n,T,m;
     4 int a[N1],L[N1],R[N1],num[N1],f[N1],id[N1];
     5 // vector<int>pos[N1];
     6 
     7 int main()
     8 {
     9     freopen("a.in","r",stdin);
    10     scanf("%d",&n);
    11     for(int i=1;i<=n;i++) scanf("%d",&a[i]);
    12     for(int i=1;i<=n;i++)
    13     {
    14         if(!L[a[i]]) L[a[i]]=R[a[i]]=i;
    15         else{
    16             R[a[i]]=i;
    17         }
    18         num[a[i]]++; id[i]=num[a[i]];
    19         // pos[a[i]].push_back(i);
    20     }
    21     int j;
    22     for(int i=n;i>=1;i--)
    23     {
    24         f[i]=f[i+1]; 
    25         if(i==L[a[i]]){
    26             f[i]=max(f[i],f[R[a[i]]+1]+num[a[i]]);
    27         }else{
    28             f[i]=max(f[i],num[a[i]]-id[i]+1);
    29         }
    30     }
    31     printf("%d
    ",n-f[1]);
    32     return 0;
    33 }
    View Code

    F AB Tree(DP+贪心)

    题目大意:给你一棵树,让你在树的每个节点上填字母,一共要填x个a,n-x个b,问如何填字母,使得根到每个节点的路径组成的串种类最少,$n=1e5$

    设根深度为1,树深度为$D$,可以讨论发现答案不是D就是D+1

    如果答案是$D$,那么所有相同深度的点字母一定相同,x个a能恰好覆盖完一些深度,其它的填b

    考虑用背包$DP$的方法来验证是否存在合法方案,设$f[j]$表示$j$能否被表示

    设$val[i]$表示点的数目,$fre[i]$表示点数为$val[i]$的深度出现的次数

    如果j能被表示,则$f[j-val[i]],f[j-2*val[i]]...f[j-fre[i]*val[i]]$中有一个能被表示

    贪心记录更大的位置,再用滚动数组转移

    不同的点数最多有$O(sqrt n)$种,DP的时间复杂度是$O(nsqrt n)$

    如果答案是$D+1$,必须有一个深度既有a又有b,而且其中的非叶节点必须填相同的字母

    设$num[i],rest[i]$分别表示深度i的节点数和非叶节点数

    现在开始分配a,设还剩p个a

    如果$p>num[i]$,把这个深度填满a

    如果$rest[i]le p<num[i]$,这个位置满足分配条件

    如果$p<rest[i]$,继续看后续有没有满足条件的深度

    可以证明这种方法一定成立,有如下性质

    $rest[i]le num[i+1]$且$rest[i]le num[i]$,$rest[D]=0$

    $rest$最后一定减少到0,容易发现一定存在$rest[i]le p<rest[i-1] le num[i]$

      1 const int N1=100005; const int M1=455; const int inf=0x3f3f3f3f;
      2 
      3 struct EDGE{
      4 int to[N1*2],nxt[N1*2],head[N1],cte;
      5 void ae(int u,int v)
      6 { cte++; to[cte]=v, nxt[cte]=head[u]; head[u]=cte; }
      7 }e;
      8 int n,D,X,Y,type,pre,cur;
      9 int fa[N1],dep[N1],num[N1],rest[N1],col[N1];
     10 vector<int>nodes[N1];
     11 
     12 void dfs(int u)
     13 {
     14     num[dep[u]]++; D=max(D,dep[u]); nodes[dep[u]].push_back(u);
     15     for(int j=e.head[u];j;j=e.nxt[j])
     16     {
     17         int v=e.to[j];
     18         dep[v]=dep[u]+1; dfs(v);
     19     }
     20     if(!e.head[u]) rest[dep[u]]++;
     21 }
     22 int ok[2][N1],id[N1],from[N1],pos[N1];
     23 int freq[N1],val[N1],used[N1],m; 
     24 
     25 void print(int ans)
     26 {
     27     printf("%d
    ",ans);
     28     for(int i=1;i<=n;i++) printf("%c",(col[i]^type)+'a'); 
     29     puts(""); 
     30 }
     31 void findway(int ma)
     32 {
     33     int now=ma,i,j,k,v;
     34     while(now)
     35     {
     36         j=from[now], i=id[now];
     37         used[val[i]]=(now-j)/val[i];
     38         now=j;
     39     }
     40     for(int i=1;i<=D;i++)
     41     {
     42         if(!used[num[i]]) continue;
     43         for(int j=0;j<nodes[i].size();j++)
     44         {
     45             v=nodes[i][j];
     46             col[v]=0;
     47         }
     48         used[num[i]]--;
     49     }
     50 }
     51 int getx(int fl)
     52 {
     53     if(fl)
     54     for(int i=1;i<=D;i++)
     55     {
     56         if(!pos[num[i]]) m++, pos[num[i]]=m, freq[m]=1, val[m]=num[i];
     57         else freq[ pos[num[i]] ]++;
     58     }
     59     memset(ok,0,sizeof(ok));
     60     int now; ok[0][0]=1; pre=0, cur=1;
     61     for(int i=1;i<=m;i++)
     62     {
     63         memcpy(ok[cur],ok[pre],sizeof(ok[cur]));
     64         for(int k=0;k<val[i];k++)
     65         {
     66             now=-1;
     67             for(int j=k;j<=X;j+=val[i])
     68             {
     69                 if(ok[pre][j]) now=j;
     70                 else if(now!=-1&& val[i]*freq[i]>=j-now) 
     71                     ok[cur][j]=1, from[j]=now, id[j]=i;
     72             }
     73         }
     74         swap(cur,pre);
     75         if(ok[pre][X]) break;
     76     }
     77     if(!ok[pre][X]) return 0;
     78     findway(X); print(D);
     79     return 1;
     80 }
     81 int fillma()
     82 {
     83     int x=X;
     84     for(int i=1;i<=D;i++) 
     85     if(x>=rest[i]&&x<=num[i])
     86     {
     87         int re=x-rest[i];
     88         for(int j=0;j<nodes[i].size();j++)
     89         {
     90             int v=nodes[i][j];
     91             if(e.head[v]) col[v]=0;
     92             else if(re) col[v]=0, re--;
     93         }
     94         print(D+1);
     95         return 1;
     96     }else if(x>num[i]){
     97         for(int j=0;j<nodes[i].size();j++)
     98         {
     99             int v=nodes[i][j]; col[v]=0;
    100         }
    101         x-=num[i];
    102     }
    103     return 0;
    104 }
    105 
    106 int main()
    107 {
    108     freopen("a.in","r",stdin);
    109     scanf("%d%d",&n,&X); Y=n-X; if(X>Y) swap(X,Y), type^=1;
    110     for(int i=2;i<=n;i++) scanf("%d",&fa[i]), e.ae(fa[i],i);
    111     dep[1]=1, dfs(1);
    112     for(int i=1;i<=D;i++) rest[i]=num[i]-rest[i];
    113     for(int i=1;i<=n;i++) col[i]=1;
    114     if(getx(1)) return 0;
    115     int ma=0, k;
    116     for(int i=1;i<=D;i++) if(num[i]>ma) ma=num[i], k=i;
    117     fillma();
    118     // if(!) fillend(); 
    119     return 0;
    120 }
    View Code
  • 相关阅读:
    2015年值得关注的8款跨平台开发工具(界面类)
    2015年最值得关注的8款用户界面新品
    2015年最受欢迎的8个用户界面组件
    DevExpress v15.2.4帮助文档下载(全)
    DevExpress .NET界面开发示例大全
    DevExpress免费线上公开课17日开课
    DevExpress 2015.2发布 看看有哪些更新
    图文详细解说DevExpress 2015新版亮点【附文档下载】
    myeclipse 2015 CI 16发布【附下载】
    swift 第三天 控制流
  • 原文地址:https://www.cnblogs.com/guapisolo/p/14409282.html
Copyright © 2011-2022 走看看