zoukankan      html  css  js  c++  java
  • Educational Codeforces Round 59 (Rated for Div. 2)

    A. Digits Sequence Dividing

    题意:给你一个长度300的,只由1-9构成的字符串,问你是否能按顺序分成至少2部分,满足每个数都比前一个数大

    题解:由于没有0,所以拆分后的数,只要满足位数比你多,就一定能完成.

            对于长度为2的单独判断,其他的直接分成2段:第一位和剩下所有

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int T,n;
     4 char s[305];
     5 int main()
     6 {
     7     scanf("%d",&T);
     8     while (T--)
     9     {
    10         scanf("%d",&n);
    11         scanf("%s",s+1);
    12         if (n==2)
    13         {
    14             if (s[1]>=s[2]) printf("NO
    ");else
    15             printf("YES
    2
    %c %c
    ",s[1],s[2]);
    16         }else
    17         {
    18             printf("YES
    2
    %c ",s[1]);
    19             for (int i=2;i<=n;i++) printf("%c",s[i]);
    20             printf("
    ");
    21         }
    22     }
    23 } 
    View Code

    B. Digital root

    题意:定义s(x)等于x的每一位之和的s(),直到小于10,例如s(38)=s(3+8)=s(11)=s(1+1)=s(2),

            现在给你多组k,x,问你满足s(n)=x的数中第k大的是多少

    题解:动手写写s(10)=1,s(11)=2,s(18)=9,s(19)=1,s(20)=2,s(27)=9,s(28)=1

            显然发现9个一循环,所以答案就是(k-1)*9+x 

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int T;
     4 long long n,m;
     5 int main()
     6 {
     7     scanf("%d",&T);
     8     while (T--)
     9     {
    10         scanf("%lld%lld",&n,&m);
    11         printf("%lld
    ",(n-1)*9+m);
    12     }
    13 } 
    View Code

    C. Brutality

    题意:给你一个2e5的只有小写字母的字符串,每个字母都有一个权值,再给你一个K,表示连续相同的字符最多只能取k个

           例如 k=3的时候,aaaa只能最多选择3个连续的进行选择,问最多能得到的权值是多少

    题意:对于每段相同的字母,排序后找最大的k个,贪心选择一下就好了

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,k;
     4 long long ans,a[200005];
     5 char s[200005];
     6 int main()
     7 {
     8     scanf("%d%d",&n,&k);
     9     for (int i=1;i<=n;i++) scanf("%d",&a[i]);
    10     scanf("%s",s+1);
    11     for (int i=1,j=1;i<=n;i=j)
    12     {
    13         while (j<=n && s[i]==s[j]) j++;
    14         sort(a+i,a+j);
    15         int p=max(j-k,i);
    16         for (int t=j-1;t>=p;t--) ans+=a[t];
    17     } 
    18     printf("%lld",ans);
    19 } 
    View Code

    D. Compression

    题意:给一个n*n(n<=5200)的01矩阵,问你能不能分成(n/x) * (n/x)的矩阵若干个,使得每个矩阵内部都是0或者都是1,问你最大x是多少

    题解:从大到小枚举到x,暴力判断每个子矩阵是否一样,感觉并太好卡暴力,因为要保证一个较小的x是答案,数据会在x更大的更快退出

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 int n,ans;
     4 char a[5202];
     5 string t[520500];
     6 int dfs(int x)
     7 {
     8     for(int i=0;i<n;i+=x)
     9     for(int j=0;j<n;j+=x)
    10     {    
    11         char ch=t[i][j];
    12         for(int k=i;k<i+x;k++)
    13         for(int p=j;p<j+x;p++) if(t[k][p]!=ch) return 0;
    14     }
    15     return 1;
    16 }
    17 int main()
    18 {
    19     scanf("%d",&n);
    20     for (int i=0;i<n;i++)
    21     {
    22         string a;
    23         cin>>a;
    24         //scanf("%s",a+1);
    25         int len=a.size();
    26         for (int j=0;j<len;j++)
    27         {
    28             if(a[j]=='0') t[i]+="0000";
    29             if(a[j]=='1') t[i]+="0001";
    30             if(a[j]=='2') t[i]+="0010";
    31             if(a[j]=='3') t[i]+="0011";
    32             if(a[j]=='4') t[i]+="0100";
    33             if(a[j]=='5') t[i]+="0101";
    34             if(a[j]=='6') t[i]+="0110";
    35             if(a[j]=='7') t[i]+="0111";
    36             if(a[j]=='8') t[i]+="1000";
    37             if(a[j]=='9') t[i]+="1001";
    38             if(a[j]=='A') t[i]+="1010";
    39             if(a[j]=='B') t[i]+="1011";
    40             if(a[j]=='C') t[i]+="1100";
    41             if(a[j]=='D') t[i]+="1101";
    42             if(a[j]=='E') t[i]+="1110";
    43             if(a[j]=='F') t[i]+="1111";
    44         }
    45     }
    46     for (int i=n;i>=1;i--)
    47     {
    48         if (n%i==0)
    49             if (dfs(i)) {ans=i;break;}
    50     }
    51     printf("%d",ans);
    52 }
    View Code

    E. Vasya and Binary String

    题意:给你一个长度100的01字符串,每次可以选连续相同的任意个字符消除,消除后两边的字符接上去,

            消去一个长度的字符串会得到一个收益,问消除完所有的能得到的最大收益是多少

    题解:典型的区间dp,dp[i][j][k]表示删除从i到j的字符串,该子串前k位和第一位一样的时候,消除的收益

            2种转移:直接消除这k个 dp[i][j][k]=a[k]+dp[i+1][j][1]

                         消除中间的,让前后连起来再消除 dp[i][j][k]=dp[i+1][q-1][1]+dp[q][j][k+1](s[q]==s[i])

             答案就是dp[1][n][1]

     1 #include<bits/stdc++.h>
     2 #define lld long long 
     3 #define N 102
     4 using namespace std;
     5 lld a[N],f[N][N][N];
     6 char s[N];
     7 int n;
     8 lld why(int st,int ed,int p)
     9 {
    10     if (st>ed) return 0;
    11     if (f[st][ed][p]!=-1) return f[st][ed][p];
    12     if (st==ed)
    13     {
    14         f[st][ed][p]=a[p];
    15         return f[st][ed][p];
    16     }
    17     f[st][ed][p]=a[p]+why(st+1,ed,1);
    18     for (int i=st+1;i<=ed;i++)
    19         if (s[i]==s[st])
    20         {
    21             f[st][ed][p]=max(f[st][ed][p],why(st+1,i-1,1)+why(i,ed,p+1));
    22         }  
    23     return f[st][ed][p];    
    24 }
    25 int main()
    26 {
    27     scanf("%d",&n);
    28     scanf("%s",s+1);
    29     for (int i=1;i<=n;i++) scanf("%lld",&a[i]);
    30     memset(f,-1,sizeof(f));
    31     printf("%lld",why(1,n,1));
    32  }
    View Code

    F. Vasya and Endless Credits

    题意:有500张信用卡,你每个月只能选择得到最多一张,a,b,k表示办这张卡的时候你得到a元,以后每个月还b元,共k个月

            你可以在任意时刻跑路(凭本事借的为什么要还),问你最多能带多少钱跑路

    题解:看起来很像费用流啊!,我们可以对每张信用卡build(S,i,1,0),再定义这是倒数第几个月build(j,T,1,0)

            信用卡对月份连接的意思就是,这张卡i在倒数第j个月的时候借了能获得的钱,(可能k大于j,还不完就跑)

            这样就能得到答案,但是复杂度有点不允许,因为边数太多.

           再发现这其实也是一个二分图且流量都一样为1,我们可以直接用二分图的最大权匹配(KM)来做,就少了一个n的代价

           好像其实这道题dp做法n*n的?快的飞起?

           (hsj板子218ms)

      1 #include <bits/stdc++.h>
      2 using namespace std;
      3 typedef long long ll;
      4 const int maxn=500+5;
      5 const int inf=0x3f3f3f3f;
      6 const ll linf=1e18;
      7 
      8 int n;
      9 
     10 ll w[maxn][maxn],slack[maxn],x[maxn],y[maxn];
     11 ll prev_x[maxn],prev_y[maxn],son_y[maxn],par[maxn];
     12 ll lx,ly,pop;
     13 void adjust(int v)
     14 {
     15     son_y[v]=prev_y[v];
     16     if(prev_x[son_y[v]]!=-2)adjust(prev_x[son_y[v]]);
     17 }
     18 
     19 bool findd(int v)
     20 {
     21     for(ll i=0;i<pop;i++)
     22         if(prev_y[i]==-1)
     23         {
     24             if(slack[i]>x[v]+y[i]-w[v][i])
     25             {
     26                 slack[i]=x[v]+y[i]-w[v][i];
     27                 par[i]=v;
     28             }
     29             if(x[v]+y[i]==w[v][i])
     30             {
     31                 prev_y[i]=v;
     32                 if(son_y[i]==-1)
     33                 {
     34                     adjust(i);
     35                     return 1;
     36                 }
     37                 if(prev_x[son_y[i]]!=-1) continue;
     38                 prev_x[son_y[i]]=i;
     39                 if(findd(son_y[i])) return 1;
     40             }
     41         }
     42     return 0;
     43 }
     44 
     45 ll km()
     46 {
     47     ll i,j,m;
     48     for(i=0;i<pop;i++)
     49     {
     50         son_y[i]=-1;
     51         y[i]=0;
     52     }
     53     for(i=0;i<pop;i++)
     54     {
     55         x[i]=0;
     56         for(j=0;j<pop;j++) x[i]=max(x[i],w[i][j]);
     57     }
     58     bool flag;
     59     for(i=0;i<pop;i++)
     60     {
     61         for(j=0;j<pop;j++)
     62         {
     63             prev_x[j]=prev_y[j]=-1;
     64             slack[j]=linf;
     65         }
     66         prev_x[i]=-2;
     67         if(findd(i))continue;
     68         flag=false;
     69         while(!flag)
     70         {
     71             m=inf;
     72             for(j=0;j<pop;j++)
     73                 if(prev_y[j]==-1) m=min(m,slack[j]);
     74             for(j=0;j<pop;j++)
     75             {
     76                 if(prev_x[j]!=-1) x[j]-=m;
     77                 if(prev_y[j]!=-1) y[j]+=m;else slack[j]-=m;
     78             }
     79             for(j=0;j<pop;j++)
     80                 if(prev_y[j]==-1&&!slack[j])
     81                 {
     82                     prev_y[j]=par[j];
     83                     if(son_y[j]==-1)
     84                     {
     85                         adjust(j);
     86                         flag=true;
     87                         break;
     88                     }
     89                     prev_x[son_y[j]]=j;
     90                     if(findd(son_y[j]))
     91                     {
     92                         flag=true;
     93                         break;
     94                     }
     95                 }
     96         }
     97     }
     98     ll ans=0;
     99     for (int i=0;i<pop;i++)ans+=w[son_y[i]][i];
    100     return ans;
    101 }
    102 
    103 ll a,b,k;
    104 int main()
    105 {
    106     //freopen("in.txt","r",stdin);
    107     scanf("%d",&n);
    108     pop=n;
    109     for (int i=0;i<n;i++)
    110     {
    111         scanf("%lld%lld%lld",&a,&b,&k);
    112         for(int j=0;j<n;j++)
    113         {
    114             ll vv=a-min(k,(ll)j)*b;
    115             w[i][j]=max(vv,0LL);
    116         }
    117     }
    118     printf("%lld
    ",km());
    119     return 0;
    120 }
    View Code

            (kuangbin板子2136ms)

     1 #include<bits/stdc++.h>
     2 using namespace std;
     3 #define N 505
     4 #define lld long long 
     5 const lld INF = 1e18;
     6 int nx,ny;//两边的点数
     7 lld g[N][N];//二分图描述
     8 int linker[N];
     9 lld lx[N],ly[N];//y中各点匹配状态,x,y中的点标号
    10 lld slack[N];
    11 bool visx[N],visy[N];
    12 bool DFS(int x)
    13 {
    14     visx[x] = true;
    15     for(int y = 0; y < ny; y++)
    16     {
    17         if(visy[y])continue;
    18         lld tmp = lx[x] + ly[y] - g[x][y];
    19         if(tmp == 0)
    20         {
    21             visy[y] = true;
    22             if(linker[y] == -1 || DFS(linker[y]))
    23             {
    24                 linker[y] = x;
    25                 return true;
    26             }
    27         }
    28         else if(slack[y] > tmp) slack[y] = tmp;
    29     }
    30     return false;
    31 }
    32 lld KM()
    33 {
    34     memset(linker,-1,sizeof(linker));
    35     //memset(ly,0,sizeof(ly));
    36     for(int i = 0;i < nx;i++)
    37     {
    38         lx[i] = -INF;
    39         for(int j = 0;j < ny;j++)
    40             if(g[i][j] > lx[i]) lx[i] = g[i][j];
    41     }
    42     for(int x = 0;x < nx;x++)
    43     {
    44         for(int i = 0;i < ny;i++) slack[i] = INF;
    45         while(true)
    46         {
    47             for (int i=0;i<nx;i++) visx[i]=0;
    48             for (int i=0;i<ny;i++) visy[i]=0;
    49             if(DFS(x))break;
    50             lld d = INF;
    51             for(int i = 0;i < ny;i++)
    52                 if(!visy[i] && d > slack[i]) d = slack[i];
    53             for(int i = 0;i < nx;i++)
    54                 if(visx[i]) lx[i] -= d;
    55             for(int i = 0;i < ny;i++)
    56                   if(visy[i])ly[i] += d; else slack[i] -= d;
    57             
    58         }
    59     }
    60     lld res = 0;
    61     for(int i = 0;i < ny;i++)
    62         if(linker[i] != -1) res += g[linker[i]][i];
    63     return res;
    64 }
    65 lld a,b,k;
    66 int main()
    67 {
    68     //freopen("in.txt","r",stdin);
    69     int n;
    70     while(scanf("%d",&n) == 1)
    71     {
    72         for (int i=0;i<n;i++)
    73         {
    74             scanf("%lld%lld%lld",&a,&b,&k);
    75             for(int j=0;j<n;j++)
    76             {
    77                 lld vv=a-min(k,(lld)j)*b;
    78                 g[i][j]=max(vv,0LL);
    79             }
    80         }
    81         nx = ny = n;
    82         printf("%lld
    ",KM());
    83     }
    84     return 0;
    85 }
    View Code

    G. Vasya and Maximum Profit

    题意:给一个n(3e5)个元素的数组ci,和一个n元素的严格上升的数组di和一个数a,求最大的a*(r-l+1)-sigma(i=l to r)c[i]-gap(l,r);

           gap(l,r)=max( (d[i+1]-d[i])^2 )(i= l to r)

    题解:首先可把a放进每一项里,a*(r-l+1)-sigma(i=l to r)c[i] 变成 sigma(i=l to r)a-c[i],这个用线段树就可以维护最大连续和

            对于gap,我们可以统计每个d[i+1]-d[i]能管的到的最长区间是多少,用单调栈O(n)预处理

            再枚举这些最大区间求区间里最大连续和就好.

     1 #include <bits/stdc++.h>
     2 using namespace std;
     3 #define LL long long 
     4 const int N = 3e5 + 10;
     5 struct tree 
     6 {
     7     LL sum, rmx, lmx, mx;
     8 }sgt[N << 2];
     9 int c[N], d[N], diff[N], a, n, l[N], r[N];
    10 long long ans;
    11 void pushup(int rt) 
    12 {
    13     sgt[rt].sum = sgt[rt << 1].sum + sgt[rt << 1 | 1].sum;
    14     sgt[rt].mx = max(sgt[rt << 1].mx, sgt[rt << 1 | 1].mx);
    15     sgt[rt].lmx = max(sgt[rt << 1].lmx, sgt[rt << 1].sum + sgt[rt << 1 | 1].lmx);
    16     sgt[rt].rmx = max(sgt[rt << 1 | 1].rmx, sgt[rt << 1 | 1].sum + sgt[rt << 1].rmx);
    17     sgt[rt].mx = max(sgt[rt].mx, sgt[rt << 1].rmx + sgt[rt << 1 | 1].lmx);
    18 }
    19 
    20 void build(int rt, int l, int r) 
    21 {
    22     if(l == r) 
    23     {
    24         sgt[rt].sum = sgt[rt].lmx = sgt[rt].rmx = sgt[rt].mx = c[l];
    25         return;
    26     }
    27     int mid = l + r >> 1;
    28     build(rt << 1, l, mid);
    29     build(rt << 1 | 1, mid + 1, r);
    30     pushup(rt);
    31 }
    32 tree query(int rt, int l, int r, int L, int R) 
    33 {
    34     if(L <= l && r <= R) return sgt[rt];
    35     int mid = l + r >> 1;
    36     if(R <= mid) return query(rt << 1, l, mid, L, R);
    37     if(L > mid)  return query(rt << 1 | 1, mid + 1, r, L, R);
    38     tree u = query(rt << 1, l, mid, L, R), v = query(rt << 1 | 1, mid + 1, r, L, R), o;
    39     o.sum = u.sum + v.sum;
    40     o.mx = max(u.mx, v.mx);
    41     o.mx = max(o.mx, u.rmx + v.lmx);
    42     o.lmx = max(u.lmx, u.sum + v.lmx);
    43     o.rmx = max(v.rmx, v.sum + u.rmx);
    44     return o;
    45 }
    46 struct node 
    47 {
    48     int val, id;
    49 };
    50 int main() 
    51 {
    52     scanf("%d%d",&n,&a);
    53     for (int i=1;i<=n;i++)
    54     {
    55         scanf("%d%d",&d[i],&c[i]);
    56         c[i]=a-c[i];
    57         ans=max(ans,(LL)c[i]);
    58     }
    59     for (int i=1;i<n;i++) diff[i]=d[i+1]-d[i];
    60     build(1,1,n);
    61     stack<node> stk;
    62     stk.push({(int)1e9, 0});
    63     for (int i=1;i<n;i++)
    64     {        
    65         while (stk.top().val<=diff[i]) stk.pop();
    66         l[i]=stk.top().id+1;
    67         stk.push({diff[i],i});
    68     }
    69     while (!stk.empty()) stk.pop();
    70     stk.push({(int)1e9,n});
    71     for (int i = n - 1; i; --i) 
    72     {
    73         while(stk.top().val <= diff[i]) stk.pop();
    74         r[i] = stk.top().id;
    75         stk.push({diff[i], i});
    76     }
    77     for(int i=1;i<n;i++)
    78         ans=max(ans, query(1,1,n,l[i],r[i]).mx - (LL)diff[i] * diff[i]);
    79     printf("%lld
    ",ans);
    80     return 0;
    81 }
    View Code

           

  • 相关阅读:
    flask 安装及基础学习(url_for反转,静态文件引入)
    collections 模块之Counter
    collections 数据结构模块namedtuple
    docker 私有仓库之Harbor搭建与使用
    ansible Api 2.3-2.4
    Ansible Callback
    saltstack returners
    快速入门Http协议
    小兔JS教程(五) 简单易懂的JSON入门
    小兔JS教程(四)-- 彻底攻略JS数组
  • 原文地址:https://www.cnblogs.com/qywhy/p/10442707.html
Copyright © 2011-2022 走看看