牛客小白月赛22【A、B、D、E、F、G、J】(题解)(持续更新)

涵盖知识点:STL、树形dp、二位前缀和etc.

比赛链接:

https://ac.nowcoder.com/acm/contest/4462#question

A:

题意见题面。

题解:直接用map维护即可。注意输入的判断。

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 map<int,int> mp;
 5 int main(){
 6     int n;
 7     cin>>n;
 8     while(n--){
 9         int t,c;
10         cin>>t;
11         char op=getchar();
12         if(op==' '){
13             cin>>c;
14             bool flag= true;
15             for(int i=t-30;i<=t+30;i++){
16                 if(mp.find(i)!=mp.end()){
17                     flag=false;
18                     break;
19                 }
20             }
21             if(flag)mp[t]=c;
22         } else{
23             if(t==-1){
24                 if(mp.empty()){
25                     cout<<"skipped
";
26                 }
27                 else{
28                     cout<<mp.begin()->second<<"
";
29                     mp.erase(mp.begin());
30                 }
31             }else{
32                 if(mp.find(t)!=mp.end())
33                     cout<<mp[t]<<"
";
34                 else
35                     cout<<"0
";
36             }
37         }
38     }
39     return 0;
40 }

B:

题意:求树链的结点和的最大值。

题解:dfs自底向上树形dp,由于负值的存在所以初值设置为无穷小。

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int inf=0x3f3f3f3f,maxn=1e5+10;
 5 vector<int> edg[maxn];
 6 ll p[maxn],dp[maxn],res=-inf;
 7 void dfs(int u,int f){
 8     dp[u]=p[u];
 9     for(auto v:edg[u]){
10         if(v==f)continue;
11         dfs(v,u);
12         res=max(res,dp[v]+dp[u]);
13         dp[u]=max(dp[u],p[u]+dp[v]);
14     }
15     res=max(res,dp[u]);
16 }
17 int main(){
18     int n;
19     cin>>n;
20     for(int i=1;i<=n;i++){
21         cin>>p[i];
22     }
23     for(int i=1;i<=n-1;i++){
24         int u,v;
25         cin>>u>>v;
26         edg[u].push_back(v);
27         edg[v].push_back(u);
28     }
29     dfs(1,0);
30     cout<<res<<"
";
31     return 0;
32 }

C:

D:

题意:一个点是起点也是终点,中间需要经过n个点,问最少走多少路。

题解:n<10,暴力求全排列取最小值即可。

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 const int inf=0x3f3f3f3f;
 5 map<int,int> mp;
 6 int p[20],x[20],y[20];
 7 int main(){
 8     int t;
 9     cin>>t;
10     while(t--){
11         int a,b,stx,sty;
12         cin>>a>>b;
13         cin>>stx>>sty;
14         int n;
15         cin>>n;
16         for(int i=0;i<n;i++)p[i]=i;
17         for(int i=0;i<n;i++)cin>>x[i]>>y[i];
18         int res=inf;
19         do{
20             int ans=abs(x[p[0]]-stx)+abs(y[p[0]]-sty)+abs(x[p[n-1]]-stx)+abs(y[p[n-1]]-sty);
21             for(int i=0;i<n-1;i++){
22                 ans+=abs(x[p[i+1]]-x[p[i]])+abs(y[p[i+1]]-y[p[i]]);
23             }
24             res=min(res,ans);
25         }while(next_permutation(p,p+n));
26         printf("The shortest path has length %d
",res);
27     }
28     return 0;
29 }

E:

题意见题面。

题解:简单容斥。

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 int main(){
 5     ll n,m,r,c;
 6     while(cin>>n>>m>>r>>c){
 7         ll res=n*m-r*m-c*n+r*c;
 8         cout<<res<<"
";
 9     }
10     return 0;
11 }

F:

题意见题面。

题解:乘d次100就打2d个0即可。

AC代码:

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 
 4 int main(){
 5     int n,d;
 6     while(cin>>n>>d){
 7         cout<<n;
 8         while(d--)cout<<"00";
 9         cout<<"
";
10     }
11     return 0;
12 }

G:

题意:在图中选一个点使全图加权距离最小。

题解:利用二位前缀和维护贡献值的正负。(据说直接暴力都能过。。。数据是真的水。。。)

AC代码:

 1 #include <bits/stdc++.h>
 2 typedef long long ll;
 3 using namespace std;
 4 const int maxn = 110;
 5 int ans[maxn][maxn];
 6 int a[maxn][maxn];
 7 int calc(int sx, int sy, int ex, int ey){
 8     ll res = a[ex][ey] - a[sx - 1][ey] - a[ex][sy - 1] + a[sx - 1][sy - 1];
 9     return res;
10 }
11 int main(){
12     int t;
13     scanf("%d", &t);
14     while (t--){
15         ans[1][1] = 0;
16         int n, m;
17         scanf("%d%d", &m, &n);
18         for (int i = 1; i <= n; i++){
19             for (int j = 1; j <= m; j++){
20                 scanf("%d", &a[i][j]);
21                 ans[i][j] = 0;
22                 ans[1][1] += a[i][j] * (i + j - 2);
23             }
24         }
25         for (int i = 1; i <= n; i++){
26             for (int j = 1; j <= m; j++){
27                 a[i][j] = a[i][j] + a[i - 1][j] + a[i][j - 1] - a[i - 1][j - 1];
28             }
29         }
30         int res = ans[1][1];
31         for (int i = 1; i <= n; i++){
32             for (int j = 1; j <= m; j++){
33                 if (i == 1 && j == 1)
34                     continue;
35                 if (j == 1){
36                     ans[i][j] = ans[i - 1][j] + calc(1, 1, i - 1, m) - calc(i, 1, n, m);
37                 }
38                 else{
39                     ans[i][j] = ans[i][j - 1] + calc(1, 1, n, j - 1) - calc(1, j, n, m);
40                 }
41                 res = min(res, ans[i][j]);
42             }
43         }
44         printf("%d
", res);
45     }
46 }

H:

I:

J:

题意见题面。

题解:拆分完字符串后模拟大数加减法。可用JAVA,也可手模。

AC代码:(C++)

 1 #include <bits/stdc++.h>
 2 using namespace std;
 3 typedef long long ll;
 4 int main(){
 5     int t;
 6     cin>>t;
 7     while(t--){
 8         string s,n1="",n2="";
 9         cin>>s;
10         int i=0;
11         while(i<s.length()&&isdigit(s[i])){
12             n1+=s[i],i++;
13         }
14         if(n1.length()==0||i==s.length()||s[i]!='+'){
15             cout<<"skipped
";
16             continue;
17         }
18         i++;
19         while(i<s.length()&&isdigit(s[i])){
20             n2+=s[i],i++;
21         }
22         if(n2.length()==0||i!=s.length()){
23             cout<<"skipped
";
24             continue;
25         }
26         //cout<<n1<<"
"<<n2<<"
";
27         if(n1.length()<n2.length())swap(n1,n2);
28         reverse(n1.begin(),n1.end());
29         reverse(n2.begin(),n2.end());
30         n1+='0';
31         for(int i=0;i<n2.length();i++){
32             n1[i]+=n2[i]-'0';
33         }
34         for(int i=0;i<n1.length()-1;i++){
35             int x=n1[i]-'0';
36             n1[i+1]+=x/10;
37             n1[i]=x%10+'0';
38         }
39         reverse(n1.begin(),n1.end());
40         for(int i=0;i<n1.length();i++){
41             if(n1[i]!='0'||i==n1.length()-1) {
42                 cout<<n1.substr(i)<<"
";
43                 break;
44             }
45         }
46     }
47     return 0;
48 }
原文地址:https://www.cnblogs.com/charles1999/p/12351412.html