涵盖知识点: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 }