当前位置: 首页 > news >正文

AtCoder Beginner Contest 409

AtCoder Beginner Contest 409

A题

知识点:枚举

题意为给了两个长度为 N N N的字符串S1S2,字符串仅包含ox字符,问两个字符串是否存在一个位置i使得S1[i]==S2[i]&&S1[i]=='o'。时间复杂度为 O ( n ) O(n) O(n)

void solve(){int n;cin >> n;string s1,s2;cin >> s1 >> s2;for(int i=0;i<n;i++){if(s1[i]==s2[i]&&s1[i]=='o'){cout << "Yes" << endl;return;}}cout << "No" << endl;
}

B题

知识点:枚举,排序+二分查找

题目陈述

给定一个长度为 N N N的非负整数序列 A = ( A 1 , A 2 , … , A N ) A = (A_1, A_2, \ldots, A_N) A=(A1,A2,,AN)。找出满足以下条件的最大非负整数 x x x

  • A A A中,大于或等于 x x x的元素出现次数(包括重复元素)至少为 x x x次。

约束条件

  • 1 ≤ N ≤ 100 1 \leq N \leq 100 1N100
  • 0 ≤ A i ≤ 10 9 0 \leq A_i \leq 10^9 0Ai109
  • 所有输入值均为整数。

解法:由于题目中要找大于等于 x x x的元素个数,所以可以对序列 A A A进行升序排序。序列最大长度不超过100,所以我们可以从0到100枚举 x x x,看那一个符合条件即可。可以使用lower_bound()函数获得大于等于 x x x的元素个数。时间复杂度为 O ( n × log ⁡ n ) O(n\times \log{n}) O(n×logn)

void solve(){int n;cin >> n;vector<int> a(n+1);for(int i=1;i<=n;i++){cin >> a[i];}sort(a.begin()+1,a.end());int x=0;for(int i=1;i<=n;i++){//枚举xint idx=lower_bound(a.begin()+1,a.end(),i)-a.begin();if(n-idx+1>=i) x=i;}cout << x << endl;
}

C题

知识点:思维,枚举

题目陈述

有一个周长为 L L L的圆,圆上放置了点 1 , 2 , … , N 1, 2, \ldots, N 1,2,,N。对于 i = 1 , 2 , … , N − 1 i = 1, 2, \ldots, N - 1 i=1,2,,N1,点 i + 1 i + 1 i+1位于点 i i i沿顺时针方向 d i d_i di距离的位置上。

请找出满足以下两个条件的整数三元组 ( a , b , c ) (a, b, c) (a,b,c) 1 ≤ a < b < c ≤ N 1 \leq a < b < c \leq N 1a<b<cN)的数量:

  • a a a b b b c c c都处于不同的位置。
  • 以点 a a a b b b c c c为顶点的三角形是等边三角形。

约束条件

  • 3 ≤ L , N ≤ 3 × 10 5 3 \leq L, N \leq 3 \times 10^5 3L,N3×105
  • 0 ≤ d i < L 0 \leq d_i < L 0di<L
  • 所有输入值均为整数。

解法:要出现等边三角形,肯定三个点中任意两个点之间的圆弧长度为 L 3 \frac{L}{3} 3L,点1的位置为0,每个点在圆周上的位置一定是一个整数,所以如果3不能整除 L L L,那么一定不存在这样的等边三角形,输出为0。否则我们计算每一个点在圆周上的位置,并且用一个 c n t cnt cnt记录每个位置点的数量,之后枚举每一个位置,计算另外两个点的位置,统计答案。这样会有一个问题就是每一个等边三角形会被重复统计,比如枚举到a点时,找到另外两个点b和c,那么枚举到b时,会找到a和c,枚举到c时,会找到a和b,那么就统计了三次,所以最后对答案除以3就是最终的答案了。时间复杂度为 O ( n ) O(n) O(n)

void solve(){int n,L;cin >> n >> L;vector<int> d(n);for(int i=1;i<n;i++) cin >> d[i];if(L/3*3!=L){cout << 0 << endl;return;}vector<int> loca(n+1);int s=0;loca[1]=s;for(int i=1;i<n;i++){s=(s+d[i])%L;loca[i+1]=s;}vector<int> cnt(L,0);for(int i=1;i<=n;i++){cnt[loca[i]]++;}int ans=0,deg=L/3;//枚举每一个位置for(int i=0;i<L;i++){int p=(i+deg)%L,q=(i+2*deg)%L;ans+=cnt[i]*cnt[p]*cnt[q];}cout << ans/3 << endl;
}

D题

知识点:贪心

问题陈述

给定一个长度为 N N N、由小写英文字母组成的字符串 S = S 1 S 2 … S N S = S_1S_2\ldots S_N S=S1S2SN。你需要对 S S S恰好执行一次以下操作:

  • 选择 S S S的一个长度至少为 1 的连续子串,将其循环左移 1 位。也就是说,选择整数 1 ≤ ℓ ≤ r ≤ N 1 \leq \ell \leq r \leq N 1rN,把 S ℓ S_\ell S插入到 S S S的第 r r r个字符右侧,然后删除 S S S的第 ℓ \ell 个字符。

找出执行该操作后,所有可能得到的字符串中字典序最小的那个。

你会拿到 T T T组测试用例,请分别解决每个测试用例。

约束条件

  • 1 ≤ T ≤ 10 5 1 \leq T \leq 10^5 1T105
  • 1 ≤ N ≤ 10 5 1 \leq N \leq 10^5 1N105
  • S S S是长度为 N N N、由小写英文字母组成的字符串。
  • T T T N N N是整数。
  • 单个输入文件中所有测试用例的 N N N之和最多为 10 5 10^5 105

解法:说到字典序,我们就会想到贪心的思想。在循环左移一次后,要使得字符串字典序是操作后最小的那个,那么肯定是找到第一个 s i > s i + 1 s_i>s_{i+1} si>si+1的位置 l l l,循环左移后 s i = s i + 1 s_i=s_{i+1} si=si+1。现在考虑字串的右端点 r r r,要将 s l s_l sl移动到后面某个位置,且满足在 l + 2 l+2 l+2到结束的某个位置 j j j使得 s j > s l s_j>s_l sj>sl,那么 r = j − 1 r=j-1 r=j1。如果不存在大于 s l s_l sl的,那么就把 s l s_l sl放在最后。这样一定是最小的,也很容易证明。最后答案就是拼接就好,可以看到上面操作至少包含了3个字符,所以对于 n ≤ 2 n \leq 2 n2的情况,我们单独处理。时间复杂度为 O ( n ) O(n) O(n)代码写的不是太好

void solve(){int n;cin >> n;string s;cin >> s;if(n<=2){if(n==1){cout << s << endl;}else{if(s[0]>s[1]){reverse(s.begin(),s.end());}cout << s << endl;}return;}string ans;bool find=false;for(int i=0;i<n-1;i++){if(s[i]>s[i+1]){find=true;//从i+2去找第一个大于当前字符的char c=s[i];ans=s.substr(0,i);ans+=s[i+1];int r=n-1,f=0;for(int j=i+2;j<n;j++){if(s[j]>c){r=j;f=1;break;}}if(f){for(int k=i+2;k<=r-1;k++) ans+=s[k];ans+=c;for(int k=r;k<n;k++) ans+=s[k];}else{for(int k=i+2;k<n;k++) ans+=s[k];ans+=c;}break;}}if(!find) cout << s << endl;else cout << ans << endl;
}

E题

知识点:树上dp

问题陈述

给定一棵有 N N N个顶点的树。顶点编号为 1 , 2 , … , N 1, 2, \ldots, N 1,2,,N,边编号为 1 , 2 , … , N − 1 1, 2, \ldots, N - 1 1,2,,N1。边 j j j双向连接顶点 u j u_j uj v j v_j vj,且权重为 w j w_j wj。此外,顶点 i i i被赋予一个整数 x i x_i xi。如果 x i > 0 x_i > 0 xi>0,则在顶点 i i i放置 x i x_i xi个正电子;如果 x i < 0 x_i < 0 xi<0,则在顶点 i i i放置 − x i -x_i xi个电子;如果 x i = 0 x_i = 0 xi=0,则顶点 i i i不放置任何粒子。已知 ∑ i = 1 N x i = 0 \sum_{i=1}^N x_i = 0 i=1Nxi=0

沿边 j j j移动一个正电子或电子需要消耗能量 w j w_j wj。当正电子和电子处于同一顶点时,它们会等量相互湮灭。

请找出使所有正电子和电子湮灭所需的最小能量。

约束条件

  • 2 ≤ N ≤ 10 5 2 \leq N \leq 10^5 2N105
  • ∣ x i ∣ ≤ 10 4 |x_i| \leq 10^4 xi104
  • ∑ i = 1 N x i = 0 \sum_{i=1}^N x_i = 0 i=1Nxi=0
  • 1 ≤ u j < v j ≤ N 1 \leq u_j < v_j \leq N 1uj<vjN
  • 0 ≤ w j ≤ 10 4 0 \leq w_j \leq 10^4 0wj104
  • 给定的图是一棵树。
  • 所有输入值均为整数。

这道题按照给出的示例模拟一下,可以发现这个就是一道树上dp的题,所以思路也很简单了,定义 d p [ i ] dp[i] dp[i]表示以 i i i为根的子树将 i i i的所有孩子向上移动能够获得的代价,由于正负电子相遇会抵消,所以要用一个 c n t [ i ] cnt[i] cnt[i]来记录每一个节点的的电子情况。之后就是列状态转移方程以及初始化等问题,可以在代码中看到。时间复杂度为 O ( n ) O(n) O(n)

示例:

5
-2 -8 10 -2 2
3 5 1
1 3 5
2 5 0
3 4 6

在这里插入图片描述

模拟一遍即可。

const int maxn=1e5+9,mod=1e9+7;
//a数组就是每个节点的电子情况,dp[i]表示以i为根的子树的花费,cnt[i]记录节点i的电子情况
int a[maxn],dp[maxn],cnt[maxn];
//tr存树
vector<pair<int,int>> tr[maxn];void dfs(int u,int p){//初始化:开始每个节点为dp[u]=0,cnt[u]=a[u]dp[u]=0;cnt[u]=a[u];for(auto[v,w]:tr[u]){if(v==p) continue;dfs(v,u);//注意这里cnt[v]要加绝对值dp[u]+=dp[v]+w*abs(cnt[v]);//湮灭电子cnt[u]+=cnt[v];}
}
void solve(){int n;cin >> n;for(int i=1;i<=n;i++) cin >> a[i];for(int i=1;i<n;i++){int u,v,w;cin >> u >> v >> w;tr[u].push_back({v,w});tr[v].push_back({u,w});}dfs(1,0);cout << dp[1] << endl;
}

相关文章:

  • OD 算法题 B卷【正整数到Excel编号之间的转换】
  • BERT
  • 自然语言处理——文本表示
  • NLP学习路线图(三十四): 命名实体识别(NER)
  • Mac M芯片 RAG 极简流程 安装 ragflow + LM studio
  • 嵌入式面试提纲
  • 网约车平台(预约打车)
  • 【Elasticsearch】映射:详解 _source store 字段
  • 【医疗电子技术】新型医疗电子和医学人工智能发展现状和趋势
  • 大数据赋能行业智能化升级:从数据价值到战略落地的全景透视
  • 听写流程自动化实践,轻量级教育辅助
  • AI书签管理工具开发全记录(十六):Sun-Panel接口分析
  • WEB3技术重要吗,还是可有可无?
  • xtp+ctp 交易系统接口简介
  • 会计-合并-5- 处置交易在合报与个报会计处理
  • C-Equilateral Triangle
  • ffmpeg(五):裁剪与合并命令
  • NY158NY159美光固态闪存NY160NY161
  • 【推荐算法】Deep Crossing:端到端深度推荐系统的奠基者
  • PLC入门【1】PLC的简单介绍(教学软件:FX-TRN-BEG-C)
  • jsp动态网站开发教材/百度指数怎么查询
  • 公司网站建设的费用/广州seo效果
  • 网站开发投标文件/百度软文推广怎么做
  • 广东网页空间网站/百度seo关键词优化软件
  • 同方云罐网站设计/南宁做网站公司
  • 阜蒙县建设镇网站/无需下载直接进入的网站的代码