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

           

  • 相关阅读:
    The Python Standard Library
    Python 中的round函数
    Python文件类型
    Python中import的用法
    Python Symbols 各种符号
    python 一行写多个语句
    免费SSL证书(https网站)申请,便宜SSL https证书申请
    元宇宙游戏Axie龙头axs分析
    OLE DB provider "SQLNCLI10" for linked server "x.x.x.x" returned message "No transaction is active.".
    The operation could not be performed because OLE DB provider "SQLNCLI10" for linked server "xxx.xxx.xxx.xxx" was unable to begin a distributed transaction.
  • 原文地址:https://www.cnblogs.com/qywhy/p/10442707.html
Copyright © 2011-2022 走看看