牛客练习赛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 }

原文地址:https://www.cnblogs.com/cmyg/p/8965166.html

时间: 2024-08-30 00:30:06

牛客练习赛16的相关文章

牛客练习赛 16

在各位ak的大佬中,我感觉我寄几好菜啊... 题目描述 给定字符串s,s只包含小写字母,请求出字典序最大的子序列. 子序列:https://en.wikipedia.org/wiki/Subsequence 字典序:https://en.wikipedia.org/wiki/Lexicographical_order 输入描述: 一行一个字符串s (1 <= |s| <= 100,000). 输出描述: 字典序最大的子序列. 示例1 输入 ababba 输出 bbba 示例2 输入 abbcb

牛客练习赛16 B求值

题目描述 给定n个数字a1, a2, ..., an.定义f(l, r) = al | al+1| ... | ar.现在枚举(1 <= l <= r <= n),问不同的f值一共有多少个. 输入描述: 第一行一个整数n表示数组大小 (1 <= n <= 100,000):第二行n个整数满足0 <= ai <= 1000,000. 输出描述: 输出一个整数表示不同的f值一共有多少个. 示例1 输入 3 1 2 0 输出 4 示例2 输入 10 1 2 3 4 5

【牛客】牛客练习赛16(未完)

A  字典序最大的子序列 题意:给定字符串s,s只包含小写字母,请求出字典序最大的子序列.(看例子就能看明白) 思路:从这个字符串a后面开始比较,先把最后一个字母存进s,然后那那s中最新的一个元素跟a中上一个进行比较,如果a不比s小,则存入s,并把这个看做新哒~ #include<bits/stdc++.h> using namespace std; typedef long long ll; const int inf = 0x3f3f3f3f; char s[100007]; int ma

牛客练习赛11 B trie树+拓扑判环 E 分治求平面最近点对

牛客练习赛11 B  假的字符串题意:给定n个字符串,互不相等,你可以任意指定字符之间的大小关系(即重定义字典序),求有多少个串可能成为字典序最小的串,并输出它们. tags:好题 对于一个字符串, 1]如有其它字符串是它的前缀,那肯定不可能.这个直接用字典树处理就可以. 2]但如果以这个字符串为最小,怎么判定其它字符串不会矛盾呢? 其实矛盾的情况详细一点说是: 比如要以  abcd 为最小, 但又有另一个字符串 aba ,这就矛盾了. 对这种情况,在跑字典树的时候,我们对有相同父亲结点的多个儿

牛客练习赛18

链接:https://www.nowcoder.com/acm/contest/110/A来源:牛客网 最大乘积 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524288K 64bit IO Format: %lld 题目描述 这题要你回答T个询问,给你一个正整数S,若有若干个正整数的和为S,则这若干的数的乘积最大是多少?请输出答案除以2000000000000000003(共有17 个零) 的余数. 举例来说,当 S = 5 时,若干个数的和为 5

转载:牛客练习赛17 c 规律题

转载:https://www.cnblogs.com/zzqc/p/8995135.html C.链接:https://www.nowcoder.com/acm/contest/109/C来源:牛客网 题目描述 给定长度为n的数组a,定义一次操作为:1. 算出长度为n的数组s,使得si= (a[1] + a[2] + ... + a[i]) mod 1,000,000,007:2. 执行a = s:现在问k次操作以后a长什么样. 输入描述: 第一行两个整数n,k(1 <= n <= 2000,

牛客练习赛7 E 珂朵莉的数列(树状数组+爆long long解决方法)

https://www.nowcoder.com/acm/contest/38/E 题意: 思路: 树状数组维护.从大佬那里学习了如何处理爆long long的方法. 1 #include<iostream> 2 #include<cstdio> 3 #include<cstring> 4 #include<algorithm> 5 using namespace std; 6 typedef long long ll; 7 const int maxn =

牛客练习赛10

A旅游观光 题目描述 有n个地方,编号为1->n,任意两个地方有公交车,从i到j的票价为(i+j)mod(n+1),而且这个票可以用无限次,你要把这些地方全部走一遍,问最小花费为多少.可以在任意地方开始和结束. 输入描述: 第一行一个数n 输出描述: 输出一行一个数表示答案 示例1 输入 10 输出 4 说明 1 -> 10 -> 2 -> 9 -> 3 -> 8 -> 4 -> 7 -> 5 -> 6,代价是4 备注: 对于100%的数据,有1

牛客练习赛1 补题记录

A 矩阵 中文题意,要找一个最大的k阶子矩阵在原矩阵中出现过两次. 需要将这个矩阵进行Hash,也就是需要二维Hash,先把每一行Hash了,再把每一列Hash了,有一点前缀的感觉. 预处理完Hash值之后,二分答案k,check过程是在$O(n ^ 2)$枚举起点,这里其实枚举终点方便一些,边界比较好处理,把每个k阶矩阵的hash值存下来,最后看有没有两个一样的. 1 #include <bits/stdc++.h> 2 using namespace std; 3 4 const int