牛客练习赛16

Posted congmingyige

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了牛客练习赛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

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

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

n=0,结果为0,

否则,

m=n%(k-1),

如果m=0,则结果为k-1,

否则结果为m。

 

对结果为0,k-1和其它 分别求解

结果为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.

结果为k-1,减去上述为0的个数。

结果为0~k-1:

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

因为内存限制,所以要进行离散化……

 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 }

 

以上是关于牛客练习赛16的主要内容,如果未能解决你的问题,请参考以下文章

牛客练习赛 16

牛客练习赛16

牛客练习赛16 E求值

牛客练习赛16 B求值

数据库练习(16年12月16日)--牛客网

数据库练习(16年12月13日)-- 牛客网