• 牛客练习赛16


    A   字典序最大的子序列 > 25960019

    一开始潜意识看成了循环,最长子串……

    找每个字母最晚出现的位置,那么比它小的字符必须出现在 在它之后的位置

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <set>
     6 #include <map>
     7 #include <list>
     8 #include <stack>
     9 #include <queue>
    10 #include <vector>
    11 #include <algorithm>
    12 #include <iostream>
    13 using namespace std;
    14 #define ll long long
    15 const long maxn=1e6+50;
    16 const ll mod=1e9+7;
    17  
    18 char s[maxn];
    19 long a[27],b[27];
    20  
    21 int main()
    22 {
    23     long len,i;
    24     scanf("%s",s);
    25     len=strlen(s);
    26     for (i=0;i<=26;i++)
    27         a[i]=-1;
    28     for (i=0;i<len;i++)
    29         a[s[i]-97]=i;
    30     b[26]=-1;
    31     for (i=25;i>=0;i--)
    32         b[i]=max(b[i+1],a[i]);
    33     for (i=0;i<len;i++)
    34         if (b[s[i]-97+1]<i)
    35             printf("%c",s[i]);
    36     return 0;
    37 }
    38 /*
    39 dsfasfaowjfwoeijwalgkargkwefaweioewajfwo
    40 */

    B   漂亮的树 > 25974107

    分奇数和偶数,最后的数之间的差值是固定的,如1,2,3,2,1 ; 1,2,2,1

    原来的数减去最终的数(以a[1]=x为基准),求出现次数最多的数。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <set>
     6 #include <map>
     7 #include <list>
     8 #include <stack>
     9 #include <queue>
    10 #include <vector>
    11 #include <algorithm>
    12 #include <iostream>
    13 using namespace std;
    14 #define ll long long
    15 const long maxn=1e5+5;
    16 const ll mod=1e9+7;
    17  
    18 long a[maxn],b[maxn*2];
    19  
    20 int main()
    21 {
    22     long n,r,i,x;
    23     scanf("%ld",&n);
    24     a[1]=0;
    25     for (i=1;i<=(long)(1.0*n/2);i++)
    26         a[i+1]=a[i]+1;
    27     for (i=n/2+1;i<=n;i++)
    28         a[i]=a[n+1-i];
    29     for (i=0;i<=1e5*2;i++)
    30         b[i]=0;
    31     for (i=1;i<=n;i++)
    32     {
    33         scanf("%ld",&x);
    34         b[x-a[i]+100000]++;
    35     }
    36     r=0;
    37     for (i=0;i<=1e5*2;i++)
    38         r=max(r,b[i]);
    39     printf("%ld",n-r);
    40     return 0;
    41 }
    42 /*
    43 5
    44 1 2 3 2 1
    45 4
    46 1 2 2 1
    47 */

    C   任意点 > 25961653

    若两点的横坐标或纵坐标相等,则它们在同一组,求组数

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <set>
     6 #include <map>
     7 #include <list>
     8 #include <stack>
     9 #include <queue>
    10 #include <vector>
    11 #include <algorithm>
    12 #include <iostream>
    13 using namespace std;
    14 #define ll long long
    15 const long maxn=1e3+5;
    16 const ll mod=1e9+7;
    17  
    18 long x[maxn],y[maxn],n;
    19 bool vis[maxn];
    20  
    21 void dfs(long d)
    22 {
    23     vis[d]=true;
    24     long i;
    25     for (i=1;i<=n;i++)
    26         if ((x[i]==x[d] || y[i]==y[d]) && !vis[i])
    27             dfs(i);
    28 }
    29  
    30 int main()
    31 {
    32     long i,c;
    33     scanf("%ld",&n);
    34     for (i=1;i<=n;i++)
    35         scanf("%ld%ld",&x[i],&y[i]);
    36     for (i=1;i<=n;i++)
    37         vis[i]=false;
    38     c=0;
    39     for (i=1;i<=n;i++)
    40         if (!vis[i])
    41         {
    42             c++;
    43             dfs(i);
    44         }
    45     printf("%ld",c-1);
    46     return 0;
    47 }

    D   k进制数 > 25967939

    额,其实要是样例没有把解题思路和易错点说得这么清晰,那这道题就是好题了……

    纸上做模拟,发现当所有位之和为R,则:

    R=0,结果为0,

    否则,设L=k-1,

    m=R%L,

    如果m=0,则结果为L,

    否则结果为m。

    证明:

    对于k进制,

    设原来的数的所有位数之和为a,当数加1,

    若进b位,则现在的数的所有位数之和为c=a+1-L*b,则c=(a+1)%L。

    对结果为0,L和其它 分别求解

    结果为0:求0的个数。如0,0,0,1,2,3,0,0,2,0,则f(3)+f(2)+f(1)=3*4/2 +  2*3/2 + 1*2/2.

    结果为L,减去上述为0的个数。因为如0,0,0,1,2中的0(1),0(2),0(3),0(1,2),0(1,3),0(2,3),0(3,3),虽然数之和除以L的余数为0,但是不符合条件

    结果为0~L-1:

    如何求子串和除以L的余数为m

    1.x(i)记录前i个数之和,

    2. g(i,M)记录所有x(j) [j=1..i]中,余数为(M-b+L)%L的个数,当x(w)=M,以第w位为结尾的子串中,子串和除以L等于b的个数为g(w-1,M)个。

    第一维单调递增,可降维。

    因为内存限制,所以要进行离散化,余数数目最多为n*2……

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <set>
     6 #include <map>
     7 #include <list>
     8 #include <stack>
     9 #include <queue>
    10 #include <vector>
    11 #include <algorithm>
    12 #include <iostream>
    13 using namespace std;
    14 #define ll long long
    15 const long maxn=1e5+5;
    16 const ll mod=1e9+7;
    17 
    18 long a[maxn],x[maxn],g[maxn*2];
    19 map<long,long>f;
    20 set<long>s;
    21 
    22 int main()
    23 {
    24     long k,b,n,i,j,num,nn;
    25     ll ans=0;
    26     scanf("%ld%ld%ld",&k,&b,&n);
    27     for (i=1;i<=n;i++)
    28         scanf("%ld",&a[i]);
    29     if (b==0)
    30     {
    31         for (i=1;i<=n;i++)
    32             if (a[i]==0)
    33             {
    34                 j=i;
    35                 while (i!=n && a[i+1]==0)
    36                     i++;
    37                 ans=ans+(long long)(i-j+2)*(i-j+1)/2;
    38             }
    39         printf("%lld",ans);
    40         return 0;
    41     }
    42     else if (b==k-1)
    43     {
    44         for (i=1;i<=n;i++)
    45             if (a[i]==0)
    46             {
    47                 j=i;
    48                 while (i!=n && a[i+1]==0)
    49                     i++;
    50                 ans=ans-(long long)(i-j+2)*(i-j+1)/2;
    51             }
    52         b=0;
    53     }
    54 
    55     k--;
    56     s.clear();
    57     x[0]=0;
    58     for (i=1;i<=n;i++)
    59     {
    60         x[i]=(x[i-1]+a[i])%k;
    61         s.insert(x[i]);
    62         s.insert((x[i]+b)%k);
    63     }
    64     s.insert(b);
    65     set<long>::iterator z;
    66     f.clear();
    67     for (z=s.begin(),num=0;z!=s.end();z++,num++)
    68         f[*z]=num;
    69     for (i=0;i<num;i++)
    70         g[i]=0;
    71     g[f[b]]=1;
    72     for (i=1;i<=n;i++)
    73     {
    74         ans=ans+(long long)g[f[x[i]]];
    75         g[f[(x[i]+b)%k]]++;
    76     }
    77     printf("%lld",ans);
    78     return 0;
    79 }
    80 /*
    81 7 6 10
    82 0 3 0 0 5 0 4 0 0 0
    83 
    84 
    85 7 6 5
    86 0 0 0 0 0
    87 
    88 7 6 6
    89 0 0 0 0 0 6
    90 
    91 7 6 8
    92 0 0 0 0 2 4 0 0
    93 
    94 7 6 9
    95 0 0 0 0 2 4 0 0 6
    96 
    97 10 5 2
    98 1 2
    99 */

    E   求值 > 25970027

    求从某个数开始,第一次 数的第i位为1的数的编号,最多有20个(2^20=1048576),从而时间复杂度O(20n)。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <set>
     6 #include <map>
     7 #include <list>
     8 #include <stack>
     9 #include <queue>
    10 #include <vector>
    11 #include <algorithm>
    12 #include <iostream>
    13 using namespace std;
    14 #define ll long long
    15 #define inf 1e9
    16 const long maxn=1e5+5;
    17 const ll mod=1e9+7;
    18  
    19 long a[maxn],nex[maxn][30];
    20 bool vis[maxn][30],use[1048576+5];
    21 long num[30];
    22  
    23 int main()
    24 {
    25     long n,b,i,j,k,g;
    26     scanf("%ld",&n);
    27     for (i=1;i<=n;i++)
    28     {
    29         scanf("%ld",&a[i]);
    30         j=0;
    31         b=a[i];
    32         while (b)
    33         {
    34             if (b & 1)
    35                 vis[i][j]=1;
    36             else
    37                 vis[i][j]=0;
    38             j++;
    39             b>>=1;
    40         }
    41     }
    42     for (j=0;j<20;j++)
    43         nex[n+1][j]=inf;
    44     for (i=n;i>=1;i--)
    45         for (j=0;j<20;j++)
    46             if (vis[i][j])
    47                 nex[i][j]=i;
    48             else
    49                 nex[i][j]=nex[i+1][j];
    50  
    51     for (i=0;i<1048576;i++)
    52         use[i]=0;
    53     for (i=1;i<=n;i++)
    54     {
    55         g=0;
    56         for (j=0;j<20;j++)
    57             if (nex[i][j]!=inf)
    58             {
    59                 num[g]=nex[i][j];
    60                 g++;
    61             }
    62         sort(num,num+g);
    63         k=a[i];
    64         use[k]=1;
    65         for (j=0;j<g;j++)
    66         {
    67             k=k | a[num[j]];
    68             use[k]=1;
    69         }
    70     }
    71     g=0;
    72     for (i=0;i<1048576;i++)
    73         if (use[i])
    74             g++;
    75     printf("%ld",g);
    76     return 0;
    77 }

    F   选值 > 25960795

    先对数排序

    用两个变量,求从一个数开始,大于等于该数且差值小于等于d的数的最远编号,这个编号一直是递增的,所以O(n)。

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <set>
     6 #include <map>
     7 #include <list>
     8 #include <stack>
     9 #include <queue>
    10 #include <vector>
    11 #include <algorithm>
    12 #include <iostream>
    13 using namespace std;
    14 #define ll long long
    15 const long maxn=1e5+5;
    16 const ll mod=1e9+7;
    17 
    18 long a[maxn];
    19 
    20 int main()
    21 {
    22     long n,d,i,k;
    23     long long r=0,g;
    24     scanf("%ld%ld",&n,&d);
    25     for (i=1;i<=n;i++)
    26         scanf("%ld",&a[i]);
    27     k=1;
    28     for (i=1;i<=n;i++)
    29     {
    30         while (k!=n && a[k+1]-a[i]<=d)
    31             k++;
    32         g=k-i;
    33         r=r+g*(g-1)/2;
    34     }
    35     printf("%lld",r);
    36     return 0;
    37 }

    或者

     1 #include <cstdio>
     2 #include <cstdlib>
     3 #include <cstring>
     4 #include <cmath>
     5 #include <set>
     6 #include <map>
     7 #include <list>
     8 #include <stack>
     9 #include <queue>
    10 #include <vector>
    11 #include <algorithm>
    12 #include <iostream>
    13 using namespace std;
    14 #define ll long long
    15 const long maxn=1e5+5;
    16 const ll mod=1e9+7;
    17  
    18 long a[maxn];
    19  
    20 int main()
    21 {
    22     long n,d,i,j,k;
    23     long long r=0,g1,g2;
    24     scanf("%ld%ld",&n,&d);
    25     for (i=1;i<=n;i++)
    26         scanf("%ld",&a[i]);
    27     k=1;
    28     for (i=1;i<=n;i++)
    29     {
    30         j=i;
    31         while (j!=n && a[j+1]==a[i])
    32             j++;
    33         k=max(k,j);
    34         while (k!=n && a[k+1]-a[i]<=d)
    35             k++;
    36         g1=j-i+1;
    37         g2=k-j;
    38         if (g1>=3)
    39             r=r+g1*(g1-1)*(g1-2)/6;
    40         if (g1>=2 && g2>=1)
    41             r=r+g1*(g1-1)/2*g2;
    42         if (g1>=1 && g2>=2)
    43             r=r+g1*g2*(g2-1)/2;
    44         i=j;
    45     }
    46     printf("%lld",r);
    47     return 0;
    48 }
  • 相关阅读:
    html5中新增的form表单属性
    FORM
    .Net Core 发布失败
    Sql Server查询最近执行sql
    HttpWebRequest.GetResponse()操作超时
    使用SqlBulkCopy批量插入/更新数据
    ADO .NET 往数据库批量插入数据发生错误:超时时间已到,但是尚未从池中获取链接
    Ueditor代码内容前台只显示一行
    Lambda表达式
    委托的简单使用
  • 原文地址:https://www.cnblogs.com/cmyg/p/8965166.html
Copyright © 2020-2023  润新知