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
",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
",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
",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
",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
",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
",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
",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
",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
",query(0,dat_n,0,0,dat_n)+1);
70         }
71     }
72     return 0;
73 }

比赛总结:

数据结构还是学的太差。

原文地址:https://www.cnblogs.com/ticsmtc/p/5993880.html