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 ...
随机推荐
- Flutter “孔雀开屏”的动画效果
老孟导读:今天分享一个类似"孔雀开屏"的动画效果,打开新的页面时,新的页面从屏幕右上角以圆形逐渐打开到全屏. 先来看下具体的效果 不知道这种效果大家叫什么名字?如果有更合适的名字可 ...
- iOS 的尾调用优化原理
背景: 今天聊代码规范的问题的时候说了一下尾调用的问题. 一:概念: 什么是尾调用? 尾调用(Tail Call):某个函数的最后一步仅仅只是调用了一个函数(可以是自身,可以是另一个函数). 注意 “ ...
- Git链接http转ssh
git remote set-url origin git@gitserver:USERNAME/PROJECT.git
- Java 对象的继承,抽象类,接口
子父级继承 关键字 extends 首先创建一个父类 class Fu { String name; int a=1; public void word() { System.out.println( ...
- iOS开发判断手机号及其运营商
根据三大运营商出现的号段(号段来自百度百科) 判断是否是手机号 + (BOOL)isMobile:(NSString *)str { NSString *MOBILE = @"^1(3[0- ...
- RabbitMQ镜像集群搭建
RabbitMQ 官网 https://www.rabbitmq.com/ 小编使用的系统环境是CentOS7.4 系统 IP hostname CentOS7.4 1.1.1.1 hostname0 ...
- ReentrantLock解析及源码分析
本文结构 Tips:说明一部分概念及阅读源码需要的基础内容 ReentrantLock简介 公平机制:对于公平机制和非公平机制进行介绍,包含对比 实现:Sync源码解析额,公平和非公平模式的加锁.解锁 ...
- 50个SQL语句(MySQL版) 建表 插入数据
本学期正在学习数据库,前段时间老师让我们做一下50个经典SQL语句,当时做的比较快,有一些也是百度的,自我感觉理解的不是很透彻. 所以从本篇随笔开始,我将进行50个经典SQL语句的复盘,加深理解. 答 ...
- java方法句柄-----5.Method Handles in Java
Method Handles in Java 目录 Method Handles in Java 1.介绍 2.什么是MethodHandle 3. Method Handles vs Reflect ...
- 面试题:我们重写一个对象的时候为什么要同时重写hashcode()和equals()方法
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 在创建的类不重写hashCode()和equals() 方法时,默认使用 java 提供的 java.l ...