NBUT TNT #1 题解报告
第一场TNT比赛,虽然三题都很水,但是只A了一题,太可惜。。赛后全都补上。
A题:
问数字A,由连续n个a(1<=a<=9) 组成,乘上数字b(1<=b<=9)所得结果中特定的数字k,有几个。比如 5 个 3 乘上 3,结果中9的个数为5个。
略水,有坑点,大部分的情况下,分为a * b 大于 10 或者不大于10的情况,但是仍然有特殊的情况,单独考虑即可。
1 #define rep(X,Y,Z) for(int X=Y;X<Z;X++)
2 #define drep(X,Y,Z) for(int X=Y;X>=Z;X--)
3 #include <iostream>
4 #include <stdio.h>
5 #include <string>
6
7 int main(){
8
9 int a , b , d , n;
10 while(~scanf("%d%d%d%d",&a,&b,&d,&n)){
11 int ans = 0;
12 if(a * b == 48){
13 if(n >= 2){
14 if(d == 8) ans = 1;
15 if(d == 2) ans = 1;
16 if(d == 3) ans = (n-2);
17 if(d == 5) ans = 1;
18 }else{
19 if(d == 4) ans = 1;
20 if(d == 8) ans = 1;
21 }
22 printf("%d\n",ans);
23 continue;
24 }
25 if(a * b == 49){
26 if(n >= 2){
27 if(d == 9) ans = 1;
28 if(d == 3) ans = 1;
29 if(d == 5) ans = 1;
30 if(d == 4) ans = (n-2);
31 }else{
32 if(d == 9) ans = 1;
33 if(d == 4) ans = 1;
34 }
35 printf("%d\n",ans);
36 continue;
37 }
38 if(a * b == 56){
39 if(n >= 2){
40 if(d == 6) ans = 2;
41 if(d == 1) ans = 1;
42 if(d == 2) ans = (n-2);
43 }else{
44 if(d == 5) ans = 1;
45 if(d == 6) ans = 1;
46 }
47 printf("%d\n",ans);
48 continue;
49 }
50 if(a * b == 28){
51 if(n >= 2){
52 if(d == 8) ans = 1;
53 if(d == 0) ans = 1;
54 if(d == 1) ans = (n-2);
55 if(d == 3) ans = 1;
56 }else{
57 if(d == 2) ans = 1;
58 if(d == 8) ans = 1;
59 }
60 printf("%d\n",ans);
61 continue;
62 }
63 if(a * b == 64){
64 if(n >= 2){
65 if(d == 4) ans = 1;
66 if(d == 0) ans = 1;
67 if(d == 7) ans = 1;
68 if(d == 1) ans = (n-2);
69 }else{
70 if(d == 6) ans = 1;
71 if(d == 4) ans = 1;
72 }
73 printf("%d\n",ans );
74 continue;
75 }
76 if(a * b < 10){
77 if(a * b == d) ans = n;
78 }else{
79 int diglw = (a*b) % 10;
80 int dighi = (a*b) / 10;
81 int digmid = dighi + diglw;
82
83 if(diglw == d) ans += 1;
84 if(digmid == d) ans += (n-1);
85 if(dighi == d) ans += 1;
86
87 }
88 printf("%d\n",ans);
89 }
90
91
92
93
94 return 0;
95 }
B题:
问最多长度为n(1<=n<=10^5)的一串数字中,有m(1<=m<=10^5)种不同的数字组成(1 - m) , 去掉其中的k (1<=k<=10^5) 个,使得最长的连续相同的数字的长度最长。
例如
1 2 1 1 2 1 1 2 1 去掉两个 那么去掉第5个和第8个最好。连续最长为1的串,长度为5.(当然去掉2,5也一样)
数据好大啊,好像也没有什么想法,只能存下每一种数字出现的位置,然后枚举起点,尺取重点。可以二分也可以直接遍历找。
1 #define rep(X,Y,Z) for(int X=Y;X<Z;X++)
2 #define drep(X,Y,Z) for(int X=Y;X>=Z;X--)
3 #define clr(X,Y) memset(X,Y,sizeof(X));
4 #include <iostream>
5 #include <stdio.h>
6 #include <string>
7 #include <vector>
8 #include <string.h>
9 #define maxN 100010
10 using namespace std;
11 vector<int> cur_pos[maxN];
12 int k;
13 void init(int in){
14 rep(i,0,in + 1) cur_pos[i].clear();
15 return ;
16 }
17 /*
18 int div(int aim , int be , int en){
19 int re = -1;
20 int l = be , r = en;
21 while(l <= r){
22 int mid = (l + r) / 2;
23 if((mid - l) - (cur_pos[mid] - cur_pos[l]) > k){
24 r = mid - 1;
25 }else{
26 l = mid + 1;
27 re = mid;
28 }
29 }
30 }
31 */
32 int div(int aim , int be ,int en){
33 int re = -1;
34 for(int i = be + 1; i <= en ; i++){
35 if(cur_pos[aim][i] - cur_pos[aim][be] - (i - be) <= k) re = i;
36 else break;
37 }
38 return re;
39 }
40 int slove(int pos){
41 int ans = 0;
42 int size = cur_pos[pos].size();
43 for(int i = 0 ; i < size ; i++){
44 int get = div(pos , i , size - 1);
45 if(get == -1) continue;
46 //printf("%d : %d : %d\n",pos,i,get);
47 ans = max(ans,get-i+1);
48 }
49 return ans;
50 }
51 int main(){
52 int T;
53 scanf("%d",&T);
54 while(T--){
55 int n , m ;
56 scanf("%d %d %d",&n,&m,&k);
57 init(m);
58 for(int i = 1; i <= n ; i++){
59 int t;
60 scanf("%d",&t);
61 cur_pos[t].push_back(i);
62 }
63 int ans = 0;
64 rep(i,1,m+1){
65 ans = max(ans,slove(i));
66 }
67 printf("%d\n",ans);
68 }
69 return 0;
70 }
C题:
有n支队伍,每一次操作给某只队伍加上分数或者减去分数,并一次加减操作后问你分数最高的队伍标号是多少,如果分数一样,则输出标号小的。
很裸的线段树RMQ,比赛的时候没敲出来,赛后1A
1 #define rep(X,Y,Z) for(int X=(Y);X<(Z);X++)
2 #define drep(X,Y,Z) for(int X=(Y);X>=(Z);X--)
3 #define clr(X,Y) memset(X,Y,sizeof(X));
4 #define INF 0x3f3f3f3f
5 #define LINF 0x3f3f3f3f
6 #include <iostream>
7 #include <stdio.h>
8 #include <string.h>
9 #include <string>
10 #include <algorithm>
11 using namespace std;
12
13 const int maxN = 1 << 17;
14 int dat_n , dat[2 * maxN - 1];
15 int val_n , val[maxN];
16 void update(int pos , int v){
17 val[pos] += v;
18 int tpos = pos;
19 pos += (dat_n - 1);
20 dat[pos] = tpos;
21 while(pos > 0){
22 pos = (pos - 1) / 2;
23 int vl = val[dat[pos * 2 + 1]];
24 int vr = val[dat[pos * 2 + 2]];
25 if(vl != vr){
26 if(vl > vr) dat[pos] = dat[pos * 2 + 1];
27 else dat[pos] = dat[pos * 2 + 2];
28 }else{
29 dat[pos] = dat[pos * 2 + 1];
30 }
31 }
32 //show_dat();
33 }
34 void bulid_tree(int n){
35 val_n = n;
36 dat_n = 1;
37 while(dat_n < val_n) dat_n *= 2;
38 //rep(i,0,2*dat_n-1) dat[i] = i;
39 rep(i,0,val_n) val[i] = 0;
40 rep(i,0,val_n){
41 update(i,0);
42 }
43 }
44 int query(int a , int b , int k , int l , int r){
45 if(r <= a || b <= l) return -1;
46 if(a <= l && r <= b) return dat[k];
47 int vl = query(a,b,k*2+1,l,(l+r)/2);
48 int vr = query(a,b,k*2+2,(l+r)/2,r);
49 if(vl < 0) return vr;
50 if(vr < 0) return vl;
51 if(val[vl] != val[vr]){
52 if(val[vl] > val[vr]) return vl;
53 else return vr;
54 }else{
55 return min(vl,vr);
56 }
57 }
58 int main(){
59 int t;
60 scanf("%d",&t);
61 while(t--){
62 int n , m;
63 scanf("%d %d",&n,&m);
64 bulid_tree(n);
65 rep(i,0,m){
66 int a , b;
67 scanf("%d %d",&a,&b);
68 update(a-1,b);
69 printf("%d\n",query(0,dat_n,0,0,dat_n)+1);
70 }
71 }
72 return 0;
73 }
比赛总结:
数据结构还是学的太差。