• 牛客小白月赛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 }
  • 相关阅读:
    selector在手机上或浏览器显示各种姿势(虚拟下拉菜单)
    关于JavaScript禁止点击事件
    设为主页以及其它功能实现
    判断浏览器是否支持flash
    渐进式增强
    判断用户Input输入的事件来进行登陆
    移动端底部input被弹出的键盘遮挡
    关于中间文字实现
    关于小程序navigator没有高的情况
    M.2接口NVMe协议的固态硬盘读写速度是SATA接口的两倍
  • 原文地址:https://www.cnblogs.com/charles1999/p/12351412.html
Copyright © 2020-2023  润新知