xdoj 2020校赛复盘
平时写东西都不喜欢复盘,这肯定不是一个好习惯,感觉每次花好几个小时甚至好几天写题目然后没写出来也不去看题解是一种很蠢的行为(
花了这么久时间打校赛,虽然水平很low,数据结构也不太会用,还是记录一下自己写的东西吧。
A
题面:
解释: 输入两行字符串之后有n个长度相同的字符串输入,判断和两个字符串对应位置相同的个数的最大值。
这道题充分的让我意识到了作为一个刷题少的人是一种怎样的体验。。就是在最基本的输入输出上都会出问题。
喜闻乐见,交了20发才过。
首先,这道题字符串总长度有\(10^6\),而计算机处理好像是1s可以处理\(10^7\)的数据量,我一开始在循环里直接用strlen()来判断字符串的长度。
for(int j=0;j<strlen(A);++j)
学长的解释:
Σ(っ °Д °;)っ
关于cin/cout,scanf,gets,fgets:
cin/cout因为需要把输入输出先存到缓冲区,所以效率低下。解决:使用 ios::sync_with_stdio(false) 取消C++对stdio的兼容。
scanf:无法读取一整行输入
gets:C++14把他移除了
fgets:用法--fgets(str,n,stdin)-----读取到换行符或者n-1个字节
ac代码:(用getchar读取好像是多余了,scanf也可以的)
#include<bits/stdc++.h>
using namespace std;
int n;
char A[1000005],B[1000005],C;
int suma=0,sumb=0,sum=0;
int main(){
int k=0;
while(scanf("%d",&n)!=EOF)
{
getchar();
while(C=getchar()){
if(C=='\n')
break;
else
A[k++]=C;
}
k=0;
while(C=getchar()){
if(C=='\n')
break;
else
B[k++]=C;
}
for(int i=0;i<n;++i){
for(int j=0;j<k;++j){
C=getchar();
if(C==A[j])
suma++;
if(C==B[j])
sumb++;
}
getchar();
sum=max(suma,sumb);
printf("%d\n",sum);
sum=0;suma=0;sumb=0;
}
k=0;
}
return 0;
}
B
题面:
看到这题开开心心点开链接玩了半小时4399....
这题是一遍过的,思路就是用栈存小球,然后两个数组分别存储每个状态下的重复球的个数和颜色,当球的个数>=3时将此状态下相同颜色小球全部出栈,当球的颜色改变时将状态数组+1并继续存。。。
ac代码:(真是又臭又长)
#include<bits/stdc++.h>
using namespace std;
#define long long ll
int arr[20005]; //存球
int cnt[20005]; //存重复颜色的个数
int tmp[20005]; //存上一个球的颜色
int n;
stack<int> st;
int judge(int k){
int tcnt=0,ttmp=0,zero=0;
tmp[ttmp]=arr[1];
if(k!=0) //k=0的情况特判
arr[2*k]=arr[2*k-1];
for(int i=0;i<2*n;){
if(arr[i]==-1)++i;
if(arr[i]!=-1){
if(arr[i]==tmp[ttmp])cnt[tcnt]++;
else if(arr[i]!=tmp[ttmp]) //当小球颜色发生变化时
{
++tcnt;
cnt[tcnt]=1;
++ttmp;//颜色变化时cnt和tmp需要把指针+1并重新计数
}
tmp[ttmp]=arr[i];
st.push(tmp[ttmp]);
if(cnt[tcnt]>=3){
if(i+2>2*n){ //最后一个了
for(int j=0;j<cnt[tcnt];++j)
st.pop(); //将相同颜色小球全部出栈
}
if(i+2<=2*n&&arr[i+2]!=-1&&arr[i+2]!=tmp[ttmp]) //如果下一个小球颜色不一样了
{
for(int j=0;j<cnt[tcnt];++j)
st.pop(); //将相同颜色小球全部出栈
if(tcnt!=0){
tcnt--;ttmp--; //返回上一个状态
}
else if(tcnt==0){
cnt[tcnt]=0;
}
}
else if(i+1<=2*n&&arr[i+1]!=-1&&arr[i+1]!=tmp[ttmp]){ //如果在插入位置
for(int j=0;j<cnt[tcnt];++j)
st.pop(); //将相同颜色小球全部出栈
if(tcnt!=0){
tcnt--;ttmp--; //返回上一个状态
}
else if(tcnt==0){
cnt[tcnt]=0;
}
}
}
}
++i;
}
zero=st.size();
while(!st.empty())st.pop(); //清空栈
memset(cnt,0,sizeof(cnt));memset(tmp,0,sizeof(tmp)); //清空cnt和tmp数组
//printf("当插入位置为k=%d时,最小的大小为size=%d\n\n",k,zero);
arr[2*k]=-1; //得把2k处的插入弄回去。
return zero;
}
int main(){
int min=99999,arrsize;
scanf("%d",&n);
int pt=0;
arr[0]=-1;
for(int i=1;i<2*n;++i){
scanf("%d",&arr[i]);
arr[++i]=-1;
}
arr[2*n]=-1;
for(int k=1;k<n+1;++k){
arrsize=judge(k);
if(min>arrsize)
min=arrsize;
}
printf("%d",min);
return 0;
}
C
题面:
解释:如矩阵所看到的,定义了交叉时对应两个字母会叉出什么新字母,求给定n个长为m的字符串看最后一共可以生成多少字符串(每个输入只能用一次)。
思路:
本题观察一下可以发现规律:
A--00
T--01
C--10
D--11
可以发现,作如上映射之后,字符交叉的关系变为了“异或”关系,如A x A = A即 00^00=00。。。
有了这个思路后,我们按照上述规则映射一下就可以很方便的列出各个交叉得到的新字符串。
我的思路是每产生一个新字符串时便将其压入set实现去重,然后多个字符串交叉可以以在set中遍历的方式进行,但是这种思路在一开始出了点小bug,就是我一开始的逻辑在输入两个相同字符串的时候我由于第一次便将其压入set的缘故直接把第二次pass掉了,于是乎我添加了一个flag判定新输入的是否在set里已有,就不执行去重的逻辑,让他可以再自交一次(
ac代码:
#include<bits/stdc++.h>
using namespace std;
map<char,int> m;
int n,k;
set<string> st;
set<string> st2;
string s,as;
string change(string A,string B){
string c;
char ss;
for(int i=0;i<k;++i){
ss=(m[A[i]])^(m[B[i]])+'0';
if(ss=='0')c+='A';
if(ss=='1')c+='T';
if(ss=='2')c+='C';
if(ss=='3')c+='G';
}
return c;
}
int main(){
int flag=1;
m['A']=0;m['T']=1;m['C']=2;m['G']=3;
cin>>n>>k;
cin>>s;
st.insert(s);
set<string>::iterator it;
for(int i=1;i<n;++i){
cin>>s;
if(!st.count(s)){
st.insert(s);flag=0;
}
for(it=st.begin();it!=st.end();it++){
if(flag==1||(flag==0&&s!=*it)){
as=change(s,*it);
if(!st.count(as))st2.insert(as);
}
}
for(it=st2.begin();it!=st2.end();it++){
if(!st.count(*it))
st.insert(*it);
}
flag=1;
}
cout<<st.size();
return 0;
}
D
解释:就是把一个数组切成三段分别求和然后让最大-最小的值最小。
思路:
二分,先把数组分为左右相差最小
for(ptr1=0;ptr1<n;++ptr1){
sum1+=a[ptr1];
if(sum1>sum/2)break;
}
从头开始找,累加到大于和的一半时停止。
然后就是又臭又长的逻辑了:
两个ptr分别指 1,2 2,3的分界,sum1,sum2,sum3存储三个的和,如果sum1>sum3的话就缩小sum1,反之缩小sum2,然后不断更新min值,直到指针到0和n-1处。(感觉会漏情况但是想不出来会漏掉哪种,总之是过了
ac代码:
#include<bits/stdc++.h>
using namespace std;
#define ll long long
#define N 1000005
ll a[N];
ll sum1=0,sum2=0,sum3=0,sum=0,minn=9223372036854775807;
int ptr1=0,ptr2=0;
void xmin(ll a,ll b,ll c){
ll ma,mi;
ma=(c>b&&c>a)?c:(a>b)?a:b;
mi=(c<a&&c<b)?c:(a<b)?a:b;
minn=min(minn,ma-mi);
}
int main(){
bool flag=0;
int n;scanf("%d",&n);
for(int i=0;i<n;++i){
scanf("%lld",&a[i]);
sum+=a[i];
}
if(sum==0)flag=1;
if(flag==0){
for(ptr1=0;ptr1<n;++ptr1){
sum1+=a[ptr1];
if(sum1>sum/2)break;
}
}
if(ptr1!=0&&ptr1!=n-1){
sum3=sum-sum1;
ptr2=ptr1+1;
sum1-=a[ptr1];
sum2+=a[ptr1];
ptr1-=1;
xmin(sum1,sum2,sum3);
}
else if(ptr1==0){
sum2=a[ptr1+1];
ptr2=ptr1+2;
sum3=sum-sum1-sum2;
xmin(sum1,sum2,sum3);
}
else if(ptr1==n-1){
ptr2=ptr1;
sum2=a[ptr1-1];
sum1=sum-a[ptr1]-sum2;
ptr1-=2;
sum3=sum-sum1-sum2;
xmin(sum1,sum2,sum3);
}
while((ptr1!=0||ptr2!=n-1)&&flag==0){
if(sum1>=sum3){
if(ptr1!=0){
sum1-=a[ptr1];sum2+=a[ptr1];
ptr1--;
xmin(sum1,sum2,sum3);
}
else if(ptr2!=n-1)
{
sum2+=a[ptr2];sum3-=a[ptr2];
ptr2++;
xmin(sum1,sum2,sum3);
}
}
else if(sum3>sum1){
if(ptr2!=n-1){
sum2+=a[ptr2];sum3-=a[ptr2];
ptr2++;
xmin(sum1,sum2,sum3);}
else if(ptr1!=0)
{
sum1-=a[ptr1];sum2+=a[ptr1];
ptr1--;
xmin(sum1,sum2,sum3);
}
}
}
if(flag==0)
printf("%lld",minn);
else
printf("0");
return 0;
}
至于官方题解,采用的是枚举l3,然后确定l2(二分查找nlogn,双指针扫描n),感觉比我这个严谨?
总结:
虽然只写了前四个水题(于我而言还挺难的,基本都是思维题,后面的图论啊数论啊dp啥的看都看不懂,还是得到了一些锻炼,感觉想法比之前全面了一点点。。
xdoj 2020校赛复盘的更多相关文章
- 2014上半年acm总结(1)(入门+校赛)
大一下学期才开始了acm,不得不说有一点迟,但是acm确实使我的生活充实了很多,,不至于像以前一样经常没事干= = 上学期的颓废使我的c语言学的渣的一笔..靠考前突击才基本掌握了语法 寒假突然醒悟, ...
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- SCNU省选校赛第二场B题题解
今晚的校赛又告一段落啦,终于"开斋"了! AC了两题,还算是满意的,英语还是硬伤. 来看题目吧! B. Array time limit per test 2 seconds me ...
- 2017CUIT校赛-线上赛
2017Pwnhub杯-CUIT校赛 这是CUIT第十三届校赛啦,也是我参加的第一次校赛. 在被虐到崩溃的过程中也学到了一些东西. 这次比赛是从5.27早上十点打到5.28晚上十点,共36小时,中间睡 ...
- HZNU第十二届校赛赛后补题
愉快的校赛翻皮水! 题解 A 温暖的签到,注意用gets #include <map> #include <set> #include <ctime> #inclu ...
- 校赛F
问题描述 例如对于数列[1 2 3 4 5 6],排序后变为[6 1 5 2 4 3].换句话说,对于一个有序递增的序列a1, a2, a3, ……, an,排序后为an, a1, an-1, a2, ...
- PKU2018校赛 H题 Safe Upper Bound
http://poj.openjudge.cn/practice/C18H 题目 算平均数用到公式\[\bar{x}=\frac{x_1+x_2+x_3+\cdots+x_n}{n}\] 但如果用in ...
- 【魔改】hdu6325 多校赛3G xy排序凸包+llvector模板
凸包算法前的预处理,可以极角排序,也可以按X,Y轴排序, 极角排序需要找到角落里的一个点,Xy轴排序要跑两遍凸包 而本题的要求只要一个上半凸包,并且有X轴从小到大以及字典序限制,完全符合xy排序,直接 ...
- 牛客网多校赛第9场 E-Music Game【概率期望】【逆元】
链接:https://www.nowcoder.com/acm/contest/147/E 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...
随机推荐
- 201771010128王玉兰《面向对象程序设计(Java)》课程学习总结
1.实验目的与要求 (1) 综合掌握java基本程序结构: (2) 综合掌握java面向对象程序设计特点: (3) 综合掌握java GUI 程序设计结构: (4) 综合掌握java多线程编程模型: ...
- 单词数(hdu2072)
这道题用到了(STL初步)集合:Set 的知识点.同时,也用到了stringstream 的知识点,还用到了getline(cin,line)的知识点. #include<iostream> ...
- MySql 常用的函数
一.聚合函数 avg(col) 计算平均值 count(col) 计算中非NULL值的个数(这个容易忘) greatest(x1,x2,...,xn) 返回集合中最大的值 ...
- UIAutomator2安装及连接
记录一下自己的偿试过程,内容来自:https://github.com/openatx/uiautomator2 d.service("uiautomator").stop()是因 ...
- go模板-代码生成器
能用程序去做的事,就不要用手,编写自己的代码生成器就是用来解放你的双手,替你做一些重复性的工作. 上篇帖子写了模板的基础 go模板详说 ,有了基础就要做点什么东西,把所学到的东西应用起来才能更好的进步 ...
- zabbix通过IPMI模式监控服务器风扇转速和温度反映机房室温变化实例
说明:2019年4月7日321机房OA服务器主板监控风扇转速和温度有明显升高,其后3天呈逐日升高趋势.检查机房感觉空调制冷量不足.4月11日联系空调维修进行处理,空调制冷恢复正常,风扇转速和温度监 ...
- Rocket - tilelink - TLBusWrapper.to
https://mp.weixin.qq.com/s/jSnhBzU5_ayQCg5fWAcx-g 简单介绍TLBusWrapper.to()的实现.主要介绍确定this{...}对应代码的过程. 1 ...
- Rocket - debug - TLDebugModuleInnerAsync
https://mp.weixin.qq.com/s/Xf4VFTHIDFh1NHmfwlTX3w 简单介绍TLDebugModuleInnerAsync的实现. 1. dmInner dmInner ...
- Linux (八)服务
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 1.服务的概念 操作系统中在后台持续运行的程序,本身并没有操作界面,需要通过端口号访问和操作.CentO ...
- Java实现 蓝桥杯 基础练习 杨辉三角形
基础练习 杨辉三角形 时间限制:1.0s 内存限制:256.0MB 提交此题 锦囊1 锦囊2 问题描述 杨辉三角形又称Pascal三角形,它的第i+1行是(a+b)i的展开式的系数. 它的一个重要性质 ...