SUM-ACM,3月24-3-31周报
两场天梯赛和一场atcoder。
主要错误知识点在于字符串的处理和并查集的掌握不够,不懂灵活运用。
- 第一场pta天梯赛
7-5 6翻了
一道字符串的题,我只拿了14分。我不熟悉一个点,f(i,0,s.length())是有问题的,在replace后,s.length()会改变,这个时候replace不是一个好的选择。
我们只需要输出的时候统计,而不需要处理再输出,边输出边处理即可。
题目如下:
14分代码如下——采用relapce的形式:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int main ()
{
int b=0;
int res =0;
string s;
getline(cin,s);
for(int i=0;i<=s.length();i++){
if(s[i]!='6')
{
if(res>3&&res<=9) {
s.replace(b, res, "9");
}
else if(res>9)
{
s.replace(b,res,"27");
}
res= 0;
b=0;
}else
{
res++;
if(res==1)
b=i;
}
}
cout<<s;
}
15分代码如下:采用输出统计数字六的数量。
点击查看代码
#include <bits/stdc++.h>
#define debug(x) cout<<#x<<":"<<x<<endl;
#define f(i,a,n) for(int i=a;i<n;++i)
#define ff(i,a,n) for(int i=a;i<=n;++i)
const int INF=0x3f3f3f3f;
using namespace std;
typedef long long ll;
//
string s;
int main(){
getline(cin,s);
s=s+'q';
int cnt=0;
for(int i=0;i<s.length();i++){
if(s[i]!='6'){
if(cnt>9){
cout<<"27";
}
else if(cnt>3){
cout<<"9";
}
else {
f(j,0,cnt)cout<<6;
}
if(i!=s.length()-1)cout<<s[i];
cnt=0;
}
else{
cnt++;
}
}
return 0;
}
7-7 估值一亿的AI核心代码
这道题也是一道字符串的题,这道题的题面不清晰,而且坑有点多。学长教的做法,先把简单容易判断的先实现比如先输出前后的空格,剩下两个一个是I could 和I,me等,我们需要特殊处理,比如说I could可以变成Is could ,后面判断的时候有一个大写字母即可区分。
题目如下:
代码如下:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define ll long long
ll get(int x) {
ll res = 1;
for (int i = 2; i <= x; i++) {
res *= i;
}
return res;
}
int main () {
ios::sync_with_stdio(0);
cin.tie(0);
int n;
cin >> n;
string s;
getline(cin, s);
while (n--) {
getline(cin, s);
cout << s << "\nAI: ";
while (s.back() == ' ') s.pop_back();
reverse(s.begin(), s.end());
while (s.back() == ' ') s.pop_back();
reverse(s.begin(), s.end());
string ans;
int cnt = 0;
for (auto& c : s) {
if (c == ' ') {
cnt++;
} else if (isalpha(c) || isdigit(c)) {
if (cnt) ans += ' ';
if (isupper(c) && c != 'I') c -= 'A' - 'a';
ans += c;
cnt = 0;
} else {
if (c == '?') c = '!';
ans += c;
cnt = 0;
}
}
auto f = [&] (const string& k, const string&v) {
int now = -1;
while ((now = ans.find(k, now + 1)) != ans.npos) {
int ok = 0;
if (now - 1 < 0 || !isalpha(ans[now-1]) && !isdigit(ans[now-1])) {
ok++;
}
if (now + k.size() >= ans.size() || !isalpha(ans[now + k.size()]) && !isdigit(ans[now + k.size()])) {
ok++;
}
if (ok == 2) {
ans.erase(now, k.size());
ans.insert(now, v);
}
}
};
f("can you", "IS can");
f("could you", "IS could");
f("I", "you");
f("me", "you");
for (int i = 0; i < ans.size(); i++) {
cout << ans[i];
if (ans[i] == 'I' && i + 1 < ans.size() && ans[i+1] == 'S') {
i++;
}
}
cout << '\n';
}
}
7-8 前世档案
这道题虽然我AC了,但我觉得还是需要放在题解里,当时我看到这道题目知道是二叉树,虽然我知道二叉树,但是它的代码我还不会写,后面找出了其中的规律,一个一个节点可以用二进制的形式表示出来,于是问题转化成了已知二进制数怎么转为整数的问题。然后我用一个pow(2,i)解决问题。
题目如下:
代码如下:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int main ()
{
int n,m;
cin>>n>>m;
getchar();
while(m--)
{
int ans =1;
string s;
getline(cin,s);
for(int i=0;i<s.length();i++){
if(s[i]=='y')
s[i]='0';
else
s[i]='1';
}
// cout<<s<<"\n";
// reverse(s.begin(),s.end());
for(int i=0;i<s.length();++i)
{
if(s[i]=='1')
ans+=pow(2,s.length()-1-i);
}
cout<<ans<<endl;
}
}
7-11 排座位
题解:这道题是并查集加上一个vector<set>的题,并查集初始化,查找,合并,路径压缩,我从这道题上学会的,还可以用vector<seint>也可以起到判断两个数的关系。
题目如下:
代码如下:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 100010
int f[N];
int find(int k)//并查集中的路径压缩
{
if(f[k]==k)return k;
return f[k]=find(f[k]);
}
void merge(int v,int u) {//合并子集
int t1,t2;//t1,t2分别为v和u的祖宗
t1=find(v);//获取祖宗结点值
t2=find(u);
if (t1!=t2) f[t2]=t1;//靠左。即将右边的集合,作为左边的子集
return;
}
int main ()
{
int k;
int n,m;
vector <set<int> > vs(n);
cin>>n>>m>>k;
for (int i = 1; i <= n; ++i) {
f[i] = i;
}
while(m--)
{
int x,y,z;
cin>>x>>y>>z;
if(z==1)
merge(x,y);
else {
vs[x].insert(y);
vs[y].insert(x);
}
}
while (k--)
{
int x,y;
cin>>x>>y;
int res =0;
if(find(x)==find(y))
{
res++;
}
if(vs[x].count(y))
{
res++;
}
if(res==0)
{
cout<<"OK"<<"\n";
}else if(res==2)
{
cout<<"OK but..."<<"\n";
}else
{
if(find(x)==find(y))
cout<<"No problem"<<endl;
else
cout<<"No way"<<endl;
}
}
}
7-10 红色警报
题解:
核心逻辑:若某城市被攻陷,则将其在地图上删除,若删除后的连通块数量增加,则该城市为核心城市。
技巧:设置一个del数组,代表该城市是否被攻陷,若是,则不参与计数。
解法一:DFS
建立地图,建立关联,每攻陷一个城市,就深搜一次,判断连通块数量是否增加。
解法二:并查集
建立结构体数组,存储所有边的信息,每攻陷一个城市,就重新建立一次并查集,判断连通块数量是否增加(注意是重新建立,而不是搜索或查询)。
题目如下:
解法一: DFS
点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
int degree[510]; //每个节点的度数
int G[510][510]; //地图
int vis[510]; //每个节点是否出现过
int del[510]; //该节点是否被删除,置1表示被删除
int n, k;
void dfs(int step) {
for(int i = 0; i < n; i++)
if(vis[i] == 0 && del[i]==0 && G[step][i]) {
vis[i] = 1;
dfs(i);
}
}
int main() {
scanf("%d %d", &n, &k);
for(int i = 0; i < k; i++) {
int x, y;
scanf("%d %d", &x, &y);
G[x][y] = G[y][x] = 1;
}
//计算最初的连通块数量
int num_line = 0; //连通块数量
for(int i = 0; i < n; i++)
if(vis[i] == 0) {
vis[i] = 1;
num_line++;
dfs(i);
}
int m; scanf("%d", &m);
for(int i1 = 0; i1 < m; i1++) {
int x; scanf("%d", &x);
//改进:直接判断连通性,若大了,则发出警告
//删除与该点有关的信息
for(int i = 0; i < n; i++)
if(G[x][i] == 1) G[x][i] = G[i][x] = 0;
del[x] = 1;
//初始化vis
memset(vis, 0, sizeof(vis));
//判断连通块数量
int num_line_after = 0;
for(int i = 0; i < n; i++)
//如果没有遍历过,并且没被删除过
if(vis[i] == 0 && del[i]==0) {
vis[i] = 1;
num_line_after++;
dfs(i);
}
//判断删除点前后的连通块数量是否相同
if(num_line < num_line_after) printf("Red Alert: City %d is lost!\n", x);
else printf("City %d is lost.\n", x);
//更新连通块的数量
num_line = num_line_after;
if(i1 == n-1) printf("Game Over.\n");
}
return 0;
}
解法2: 结构体+并查集(这个时间复杂度更低)
点击查看代码
#include<iostream>
#include<cstdio>
#include<cstring>
using namespace std;
struct node{
int x, y;
}edge[5005];
int pre[510]; //存放并查集
int del[510]; //该节点是否被删除,置1表示被删除
int n, k;
int find(int x) {
return x == pre[x] ? x : pre[x] = find(pre[x]);
}
void Union(int x, int y) {
int fx = find(x);
int fy = find(y);
if(fx != fy) pre[fx] = fy;
// if(fx > fy) pre[fx] = fy;
// else pre[fy] = fx;
}
int main() {
scanf("%d %d", &n, &k);
for(int i = 0; i < n; i++) pre[i] = i; //并查集初始化
for(int i = 0; i < k; i++) {
scanf("%d %d", &edge[i].x, &edge[i].y);
Union(edge[i].x, edge[i].y);
}
int num_line_before = 0; //攻占某城市前连通块数量
for(int i = 0; i < n; i++) if(pre[i] == i) num_line_before++;
int m; scanf("%d", &m);
for(int i1 = 0; i1 < m; i1++) {
int x; scanf("%d", &x);
del[x] = 1;
for(int i = 0; i < n; i++) pre[i] = i;
for(int i = 0; i < k; i++) {
if(!del[edge[i].x] && !del[edge[i].y]) {
Union(edge[i].x, edge[i].y);
}
}
int num_line_after = 0; //攻占某城市后连通块数量
for(int i = 0; i < n; i++) if(pre[i] == i && !del[i]) num_line_after++;
if(num_line_after > num_line_before) printf("Red Alert: City %d is lost!\n", x);
else printf("City %d is lost.\n", x);
if(i1 == n-1) printf("Game Over.\n");
num_line_before = num_line_after;
}
return 0;
}
- 第二场天梯赛
7-4 谁能进图书馆
题解:我当时拿了9分,满分10分,我分析了原因,我读题不清晰,不知道两个人都进不去有两行输出。
题目如下:
代码如下:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int main()
{
int n,m,k,l;
cin>>n>>m>>k>>l;
//禁入年龄线 陪同年龄线 询问者1的年龄 询问者2的年龄
if(k>=m&&l<n)
{
cout<<k<<"-Y"<<" ";
cout<<l<<"-Y";
cout<<"\n";
cout<<"qing 1 zhao gu hao 2";
}else if(k<n&&l>=m)
{
cout<<k<<"-Y"<<" ";
cout<<l<<"-Y";
cout<<"\n";
cout<<"qing 2 zhao gu hao 1";
}
else if(k<n&&l<n)
{
cout<<k<<"-N"<<" ";
cout<<l<<"-N";
cout<<"\n";
cout<<"zhang da zai lai ba";
}
else if(k<m&&k>n&&l<n)
{
cout<<k<<"-Y"<<" ";
cout<<l<<"-N";
cout<<"\n";
cout<<"1: huan ying ru guan";
}else if(k<n&&l>n&&l<m)
{
cout<<k<<"-N"<<" ";
cout<<l<<"-Y";
cout<<"\n";
cout<<"2: huan ying ru guan";
}
else
{
cout<<k<<"-Y"<<" ";
cout<<l<<"-Y";
cout<<"\n";
cout<<"huan ying ru guan";
}
}
7-7 出租
题解:由题目可知,第一个中数组的数都是不一样的,而且是从大到小,所以我们可以先解决上面的数组然后再搞定下面的数组,根据上面数组的特点,
我想到了堆,用** set<int,greater>arr;**就可以从大到小记录每一个数。
然后我们就可以知道tle中每一个在index中的每一个数对应上面set的下标对应的值就可以得出下面数组的每一个值。有一个问题就是set是不会记录下标的,
因为堆的原理是二叉树,下标没有意义,但是这个题中是有意义的,我们可以用一个变量来记录第几位即可。
题目如下:
代码如下:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
int main ()
{
set<int,greater<int>>arr;
vector<int>index;
string s;
cin>>s;
for(int i=0;i<s.length();i++){
arr.insert(s[i]-'0');
}
for(int i=0;i<s.length();i++){
int rs =0;
for ( set<int>::iterator it = arr.begin(); it != arr.end(); it++){
rs++;
if (*it == s[i]-'0')
{
index.push_back(rs);
}
}
}
cout<<"int[] arr = new int[]{";
int res =0;
for(set<int>::iterator i=arr.begin();i!=arr.end();i++)
{
res++;
cout<<*i;
if(res<arr.size())
cout<<",";
}
cout<<"};"<<endl;
cout<<"int[] index = new int[]{";
for(int i=0;i<index.size();i++){
cout<<index[i]-1;
if(i<index.size()-1)
cout<<",";
}
cout<<"};"<<endl;
}
7-7 连续因子
题解:1.一个数再sqrt(a)-a之间肯定不会有连续因子,所以从2-sqrt(a)循环
2.另用一个变量被循环的i赋值,寻找最长的连续因子。每次循环完将count回到0,并记录最长开始的i。
3.输出,先输出最开始,然后循环依次输出*和开始+1.
这种做法虽然拿不了满分,但是大部分样例都没问题,是拿分的一个好思路。
题目如下:
18分代码如下:
点击查看代码
#include <bits/stdc++.h>
int main()
{
int a,n,max=0;
int count,begin;
int b[10001];
scanf("%d",&a);
for(int i=2;i<=sqrt(a);i++)
{
n=a;
count=0;
int j=i;
while(n%j==0)
{
n/=j;
j++;
count++;
}
if(count>max)
{
max=count;
begin=i;
}
}
if(max)
{
printf("%d\n",max);
printf("%d",begin);
for(int c=1;c<max;c++)
{
printf("*");
printf("%d",begin+c);
}
}
}
7-12 文件传输
题解:这道题目依旧是并查集,不过我当时没有想到用并查集,用set维护,可以骗11分,正确的做法就是并查集。
一道简单的并查集,最后就是一个小问题,如何判断是否都在一个集合里面我们只需要
一个for循环判断有多少个f[i]==i,然后cnt加加,因为都在一个集合里面只会有一个f[i]=i
如果cnt==1说明都在一起,否则输出cnt个
题目如下:
代码如下:
点击查看代码
#include <bits/stdc++.h>
using namespace std;
#define N 100010
int f[N];
int del[N]; //该节点是否被删除,置1表示被删除
struct node{
int x, y;
}edge[5005];
int find(int k)//并查集中的路径压缩
{
if(f[k]==k)return k;
return f[k]=find(f[k]);
}
void merge(int v,int u) {//合并子集
int t1,t2;//t1,t2分别为v和u的祖宗
t1=find(v);//获取祖宗结点值
t2=find(u);
if (t1!=t2) f[t2]=t1;//靠左。即将右边的集合,作为左边的子集
return;
}
int main ()
{
int pd=0;
int res=0;
int n;
cin>>n;
for (int i = 1; i <=n ; ++i) {
f[i]=i;
}
char a;int x,y;
while(cin>>a)
{
if(a=='S')
{
for (int i = 1; i <=n ; ++i) {
if(f[i]==i)
{
res++;
}
}
if(res==1)
{
printf("The network is connected.");
}else
printf("There are %d components.",res);
}else
{
cin>>x>>y;
if(a=='C')
{
if(find(x)== find(y))
cout<<"yes"<<"\n";
else
cout<<"no"<<"\n";
}else if(a=='I')
merge(x,y);
}
}
}
7-9 哈利·波特的考试
7-10 列车厢调度
题解:用栈存
7-11 病毒溯源
补题中-----
* **atcoder**
我只写出了两道题,我分享一下第二道题,我感觉是字符串一个很好用的寻找子串的方法。我们只需要建立两个for循环,然后让strsub方法去截取里面的字符,用set维护即可找到不同的子串
题目如下:
代码如下:
点击查看代码
#include <iostream>
#include <string>
#include <set>
int countSubstrings(const std::string& S) {
std::set<std::string> substrings;
for (size_t i = 0; i < S.length(); ++i) {
for (size_t j = i+1; j <= S.length(); ++j) {
substrings.insert(S.substr(i, j-i));
}
}
return substrings.size();
}
int main() {
std::string S;
std::cin >> S;
int result = countSubstrings(S);
std::cout << result << std::endl;
return 0;
}
SUM-ACM,3月24-3-31周报的更多相关文章
- 9月24日开始发布,主打安全的Librem 5 Linux手机
曾推出搭载PureOS Linux发行版本Librem笔记本系列的硬件厂商Purism,今天正式宣布了Librem 5 Linux手机的最终和官方发售日期.Librem 5于2017年10月正式发布, ...
- SQL PASS将于8月24日在北京中医药大学举办线下活动
活动主题:复制架构的实现和调优以及SQL Server BI在传统行业的应用 地点:北三环东路11号 北京中医药大学 白色的1号楼教学楼后楼5层511房间 时间:2013年8月24日 9:00-12: ...
- 2016年12月24日 星期六 --出埃及记 Exodus 21:19
2016年12月24日 星期六 --出埃及记 Exodus 21:19 the one who struck the blow will not be held responsible if the ...
- 2016年11月24日 星期四 --出埃及记 Exodus 20:15
2016年11月24日 星期四 --出埃及记 Exodus 20:15 "You shall not steal.不可偷盗.
- 2016年10月24日 星期一 --出埃及记 Exodus 19:8
2016年10月24日 星期一 --出埃及记 Exodus 19:8 The people all responded together, "We will do everything th ...
- 2016年6月24日 星期五 --出埃及记 Exodus 14:21
2016年6月24日 星期五 --出埃及记 Exodus 14:21 Then Moses stretched out his hand over the sea, and all that nigh ...
- 6月24日AppCan移动开发者大会礼品清单遭泄露
6月24日,第一届AppCan移动开发者大会将在北京国际会议中心举办,大会以”平台之上,应用无限”为主题,全景展现移动应用发展趋势.AppCan 移动技术蓝图及80万开发者的技术实践成果. 大会现场礼 ...
- Web安全测试周末公开班计划5月24、25日开课,欢迎报名参加!
Web安全测试周末公开班计划5月24.25日开课,欢迎报名参加! 课程大纲参考: http://gdtesting.com/product.php?id=107 报名咨询: 黎小姐 QQ:241448 ...
- 2018年3月24日上海MVP线下技术交流活动简报
2018年3月24日下午,几位上海MVP自发组织了一次线下的技术交流会,主要由MVP胡浩牵头,我(陈晴阳).刘鑫.朱兴亮和胡浩各自做了一次主题演讲,具体主题是: 陈晴阳:<这还是我认识的Visu ...
- 北京Uber优步司机奖励政策(4月24日)
滴快车单单2.5倍,注册地址:http://www.udache.com/ 如何注册Uber司机(全国版最新最详细注册流程)/月入2万/不用抢单:http://www.cnblogs.com/mfry ...
随机推荐
- 使用 TortoiseGit 时,报 Access denied 错误
当输入正确的密码时,总是报如下错误: 解决方法: 然后弹出如下对话框: 然后编辑本地配置文件: 然后将红色框的SSH配置改为绿色框的 HTTP配置,点击保存,确定. 然后再进行拉取源码,先输入用户名, ...
- 企业生产环境中的麒麟V10(ARM架构)操作系统部署jdk和redis三主三从交叉版集群
前言:麒麟ARM操作系统是国企和政务机关推行信创化选择率比较高的一款操作系统,然而ARM操作系统非主流的X86系统,除了命令一样,在架构方面差别极大,初次接触多多少少会踩坑,下面我将在公司中部署的实例 ...
- 【进阶篇】使用 Stream 流对比两个集合的常用操作分享
目录 前言 一.集合的比较 1.1需要得到一个新的流 1.2只需要一个简单 boolean 结果 二.简单集合的对比 2.1整型元素集合 2.2字符串元素集合 2.3其它比较 三.Stream 基础回 ...
- vim快捷键之复制粘贴
yy: 复制光标所在行 p: 将复制的内容粘贴到光标所在行的下一行 P: 将复制的内容粘贴到光标所在行的上一行
- Android 13 - Media框架(29)- MediaCodec(四)
关注公众号免费阅读全文,进入音视频开发技术分享群! 上一节我们了解了如何通过 onInputBufferAvailable 和 getInputBuffer 获取到 input buffer inde ...
- 如何判断7z压缩文件格式
如果压缩文件的后缀不是7z,那么如何如何判断文件格式呢?那就是通过文件头判断. 7z文件头前6位,固定是:377ABCAF271C,其中前两位37.7A分别是"7""z& ...
- JS+DOM简要笔记
js官方文档: https://www.w3school.com.cn/js/index.asp 简单理解:html是内容,css是控制样式,js是行为. 1,js弱类型特点 JavaScript 是 ...
- 算法金 | 读者问了个关于深度学习卷积神经网络(CNN)核心概念的问题
大侠幸会,在下全网同名[算法金] 0 基础转 AI 上岸,多个算法赛 Top [日更万日,让更多人享受智能乐趣] 读者问了个关于卷积神经网络核心概念的问题,如下, [问]神经元.权重.激活函数.参数 ...
- Python使用.NET开发的类库来提高你的程序执行效率
Python由于本身的特性原因,执行程序期间可能效率并不是很理想.在某些需要自己提高一些代码的执行效率的时候,可以考虑使用C#.C++.Rust等语言开发的库来提高python本身的执行效率.接下来, ...
- 利用.htaccess绑定子域名到子目录
Tips:当你看到这个提示的时候,说明当前的文章是由原emlog博客系统搬迁至此的,文章发布时间已过于久远,编排和内容不一定完整,还请谅解` 利用.htaccess绑定子域名到子目录 日期:2018- ...