比赛地址:https://ac.nowcoder.com/acm/contest/77526
开错题了,赛时就出了5题;
补题顺带写一下记录
A:小苯的区间和疑惑
链接:https://ac.nowcoder.com/acm/contest/77526/A
大意:给一个数组\(a\),让你对数组中每一个数\(a_i\),求包含这个数的一个区间,要求这个区间的值的和最大;
可以直接贪心,即分别从左到右,从右到左求一次最大连续子序列和(这个不会可以看看这题:https://leetcode.cn/problems/maximum-subarray/description/),
求出左右两侧(左侧用数组\(l\)记录,右侧用数组\(r\)记录,看你喜欢怎么记)的最大子序列和后,直接\(a_i\)+\(l_{i-1}\)+\(r_{i+1}\)就可以得出答案,复杂度为\(O(n)\);
AC代码:
// author:manjuan
//
#include <bits/stdc++.h>
#define N 1001
using namespace std;
using ll = long long;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
ll n;
cin>>n;
vector<ll> v(n+2),sum(n+2),l(n+2),r(n+2);;
for(int i=1;i<=n;i++)cin>>v[i];
for(int i=1;i<=n;i++){
l[i]=v[i]+l[i-1];
if(l[i]<0)l[i]=0;
//cout<<l[i]<<" ";
}//cout<<"\n";
for(int i=n;i>0;i--){
r[i]=v[i]+r[i+1];
if(r[i]<0)r[i]=0;
}
for(int i=1;i<=n;i++){
sum[i]=v[i]+l[i-1]+r[i+1];
cout<<sum[i]<<" ";
}
}
B:小苯的三元组
链接:https://ac.nowcoder.com/acm/contest/77526/B
大意:给你一个n和一个长度为n的数组a,让你找满足条件\(lcm\)(\(a_i\),\(a_j\))\(\leq\)\(gcd\)(\(a_j\),\(a_k\))\(的三元组(\)a_i\(,\)a_j\(,\)a_k$)的数量。
赛时没出,其实不难想到:由于值域为\(1\)到\(2\)x\(10^5\),所以可以用桶(用数组a来存,也可以用map或者unordered_map,这里开int数组可以存下,但是数据量最大到\(2\)x\(10^5\),数据设置特殊一点是可以卡爆int的,所以得开long long)去装每一个数的个数;然后对于每一个在\(1\)到\(2\)x\(10^5\)间的i都跑一个三层循环(此循环实际上复杂度为调和级数级,即约\(n\)\(logn\)),
然后对于每一个\(a_i\),找为其整数倍的\(a_j\),对于每一个\(a_j\),找为其整数倍的\(a_k\)\(a_i\)、\(a_j\)、\(a_k\)的数量之积的和即为答案;
AC代码(实际上还可以再优化,但不优化也才跑87ms)
// author:manjuan
//
#include <bits/stdc++.h>
#define N 200005
using namespace std;
using ll = long long;
ll a[N];
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
ll n,ans{0};
cin>>n;
for(int i=1;i<=n;i++){
int x;
cin>>x;
a[x]++;
}
for(int i=1;i<N;i++){
for(int j=i;j<N;j+=i){
for(int k=j;k<N;k+=j){
//if(a[i]&&a[j]&&a[k]){
// cout<<i<<" "<<j<<" "<<k<<endl;
//}
ans+=(a[i]*a[j]*a[k]);
}
}
}
cout<<ans<<"\n";
}
C:小红的 CUC
签到题,记得特判
D:小红的矩阵构造(一)
链接:https://ac.nowcoder.com/acm/contest/77526/D
大意:给你两个长度为n的排列A和B,让你构造一个\(n\)x\(n\)的矩阵,要求矩阵的第\(i\)行有\(a_i\)个1,第\(j\)列有\(b_j\)个1;
不是太难,选择行或列进行填充,用两个pair记录第\(i\)\(/\)\(j\)行\(/\)列需要几个1,然后顺序的去对每一行\(/\)列进行填充,对于从行选取,则对该行需求仍大于0时,对需求大于0的列填充一个1,然后填充位置的行和列需求均减1;可以用数组在空间上进行优化,但是1A了,就没有再去优化;
AC代码:
// author:manjuan
//
#include <bits/stdc++.h>
#define N 1005
using namespace std;
using ll = long long;
int c[N][N];
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
int n;
cin>>n;
vector<pair<int,int>> pc(n),pr(n);
for(int i=0;i<n;i++){
cin>>pc[i].first;
pc[i].second=i+1;
}sort(pc.begin(),pc.end(),greater<pair<int,int>>());
for(int i=0;i<n;i++){
cin>>pr[i].first;
pr[i].second=i+1;
}
for(int i=0;i<n;i++){
while(pc[i].first>0){
for(int j=0;j<n;j++){
if(pr[j].first>0){
//cout<<pc[i].second<<" "<<pr[j].first<<" "<<pr[j].second<<"\n";
c[pc[i].second][pr[j].second]++;
pr[j].first--;
pc[i].first--;
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<c[i][j];
}cout<<"\n";
}
}
E:小红的矩阵构造(二)
链接:https://ac.nowcoder.com/acm/contest/77526/D
很简单,第一个正方形需要四个1,第一行和列后续需要的正方形需要添两个1,再之后每个新正方形都只需要一个1;顺序填充即可;注意题目数据范围,添加特判条件;
AC代码:
// author:manjuan
//
#include <bits/stdc++.h>
#define N 1005
using namespace std;
using ll = long long;
int c[N][N];
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
int n;
cin>>n;
vector<pair<int,int>> pc(n),pr(n);
for(int i=0;i<n;i++){
cin>>pc[i].first;
pc[i].second=i+1;
}sort(pc.begin(),pc.end(),greater<pair<int,int>>());
for(int i=0;i<n;i++){
cin>>pr[i].first;
pr[i].second=i+1;
}
for(int i=0;i<n;i++){
while(pc[i].first>0){
for(int j=0;j<n;j++){
if(pr[j].first>0){
//cout<<pc[i].second<<" "<<pr[j].first<<" "<<pr[j].second<<"\n";
c[pc[i].second][pr[j].second]++;
pr[j].first--;
pc[i].first--;
}
}
}
}
for(int i=1;i<=n;i++){
for(int j=1;j<=n;j++){
cout<<c[i][j];
}cout<<"\n";
}
}
F:
G:小红的独特区间
链接:https://ac.nowcoder.com/acm/contest/77526/G
大意:给你一个\(n\),和一个长度为\(n\)的数组\(a\),问你有多少连续的子序列满足恰好有三种不同的元素;
先预处理出从位置\(i\)向左需要删多少个元素才能使这一段元素数量恰好等于3,和从位置\(i\)向右需要删多少个元素使这一段元素数量恰好等于2,再将第二个预处理的数组加一,再统计一下即可
AC代码:
// author:manjuan
//
#include <bits/stdc++.h>
#define N 1005
using namespace std;
using ll = long long;
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
int n;
cin>>n;
vector<int> a(n);
for(int i{0};i<n;i++)cin>>a[i];
map<int,int> mp;
vector<int > l(n,-1),r(n,-1);
// 接下来开始离散化
for(int i{0},j{0};i<n;i++){
mp[a[i]]++;
while(mp.size()>3){
if(!--mp[a[j]]){
mp.erase(a[j]);
}
j++;
}
if(mp.size()==3){
l[i] = j;
}
}
//for(int i{0};i<n;i++){cout<<l[i]<<" ";}
mp={};//今天才发现可以这样清空map;
for(int i{0},j{0};i<n;i++){
mp[a[i]]++;
while(mp.size()>2){
if(!--mp[a[j]]){
mp.erase(a[j]);
}
j++;
}
if(mp.size()==2){
r[i]=j;
}
}
//cout<<"\n";
//for(int i{0};i<n;i++){cout<<r[i]<<" ";}
ll ans{0};
for(int i{0};i<n;i++){
if(l[i]!=-1&&r[i]!=-1){
ans+=r[i]-l[i];
}
}
cout<<ans<<"\n";
return 0;
}
H:小红的生物实验
链接:https://ac.nowcoder.com/acm/contest/77526/H
注意题目只保证只要一个完整细胞,但不保证没有不完整细胞,故从四个方向各向内侧扫一次扫到第一个细胞壁进行清楚的做法错误;
正解使用BFS;
首先对整个图的四个外侧都加一个 \(.\),防止细胞大小为全图,然后从随便一个刚刚加的\(.\)开始跑BFS,遇见\(*\)进行标记和删除,且不将其坐标放入队列,一次BFS即可;
AC代码:
// author:manjuan
//
#include <bits/stdc++.h>
#define N 1005
using namespace std;
using ll = long long;
char c[N][N];
int a[N][N];
vector<vector<bool>> vis(N, vector<bool>(N, false));
pair<int,int> p[]={{0,1},{0,-1},{1,0},{-1,0}};
int main()
{
ios_base::sync_with_stdio(false);
cin.tie(NULL);cout.tie(NULL);
int n,m;
cin>>n>>m;
for(int i=1;i<=n;i++) {
for (int j = 1; j <= m; j++) {
cin>>c[i][j];
}
}
for(int i=0;i<=n+1;i++) {
c[i][0]='.';
}for(int i=0;i<=n+1;i++) {
c[i][m+1]='.';
}for(int i=0;i<=m+1;i++) {
c[0][i]='.';
}for(int i=0;i<=m+1;i++) {
c[n+1][i]='.';
}
queue<pair<int,int>> q;
q.emplace(0,0);
while(!q.empty()) {
auto [x,y]=q.front();
vis[x][y]=true;
q.pop();
for(auto [a1,b1]:p) {
if(c[x+a1][y+b1]=='.'&&!vis[x+a1][y+b1]) {
q.emplace(x+a1,y+b1);
vis[x+a1][y+b1]=true;
}
if(c[x+a1][y+b1]=='*') {
c[x+a1][y+b1]='.';
vis[x+a1][y+b1]=true;
}
}
}
//for(int i=1;i<=n;i++) {
// for (int j = 1; j <= m; j++) {
// if(c[i][j] == '*') {
// a[i][j]++;
// break;
// }
// }
//}
//for(int i=1;i<=n;i++) {
// for (int j = m; j >= 1; j--) {
// if(c[i][j] == '*') {
// a[i][j]++;
// break;
// }
// }
//}
//for(int j=1;j<=m;j++) {
// for(int i=1;i<=n;i++) {
// if(c[i][j] == '*') {
// a[i][j]++;
// break;
// }
// }
//}
//for(int j=1;j<=m;j++) {
// for(int i=n;i>=1;i--) {
// if(c[i][j] == '*') {
// a[i][j]++;
// break;
// }
// }
//}
for(int i=1;i<=n;i++) {
for(int j=1;j<=m;j++) {
cout<<c[i][j];
}cout<<"\n";
}
}
浙公网安备 33010602011771号