平时写东西都不喜欢复盘,这肯定不是一个好习惯,感觉每次花好几个小时甚至好几天写题目然后没写出来也不去看题解是一种很蠢的行为(

花了这么久时间打校赛,虽然水平很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校赛复盘的更多相关文章

  1. 2014上半年acm总结(1)(入门+校赛)

    大一下学期才开始了acm,不得不说有一点迟,但是acm确实使我的生活充实了很多,,不至于像以前一样经常没事干=  = 上学期的颓废使我的c语言学的渣的一笔..靠考前突击才基本掌握了语法 寒假突然醒悟, ...

  2. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  3. SCNU省选校赛第二场B题题解

    今晚的校赛又告一段落啦,终于"开斋"了! AC了两题,还算是满意的,英语还是硬伤. 来看题目吧! B. Array time limit per test 2 seconds me ...

  4. 2017CUIT校赛-线上赛

    2017Pwnhub杯-CUIT校赛 这是CUIT第十三届校赛啦,也是我参加的第一次校赛. 在被虐到崩溃的过程中也学到了一些东西. 这次比赛是从5.27早上十点打到5.28晚上十点,共36小时,中间睡 ...

  5. HZNU第十二届校赛赛后补题

    愉快的校赛翻皮水! 题解 A 温暖的签到,注意用gets #include <map> #include <set> #include <ctime> #inclu ...

  6. 校赛F

    问题描述 例如对于数列[1 2 3 4 5 6],排序后变为[6 1 5 2 4 3].换句话说,对于一个有序递增的序列a1, a2, a3, ……, an,排序后为an, a1, an-1, a2, ...

  7. 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 ...

  8. 【魔改】hdu6325 多校赛3G xy排序凸包+llvector模板

    凸包算法前的预处理,可以极角排序,也可以按X,Y轴排序, 极角排序需要找到角落里的一个点,Xy轴排序要跑两遍凸包 而本题的要求只要一个上半凸包,并且有X轴从小到大以及字典序限制,完全符合xy排序,直接 ...

  9. 牛客网多校赛第9场 E-Music Game【概率期望】【逆元】

    链接:https://www.nowcoder.com/acm/contest/147/E 来源:牛客网 时间限制:C/C++ 1秒,其他语言2秒 空间限制:C/C++ 262144K,其他语言524 ...

随机推荐

  1. poj2594最小路径覆盖+floyd

    Treasure Exploration Time Limit: 6000MS   Memory Limit: 65536K Total Submissions: 8909   Accepted: 3 ...

  2. MySql 常用的函数

    一.聚合函数 avg(col)      计算平均值    count(col)    计算中非NULL值的个数(这个容易忘)    greatest(x1,x2,...,xn) 返回集合中最大的值  ...

  3. 《机器学习_09_01_决策树_ID3与C4.5》

    简介 先看一个例子,某银行是否给用户放贷的判断规则集如下: if 年龄==青年: if 有工作==是: if 信贷情况==非常好: 放 else: 不放 else: if 有自己的房子==是: if ...

  4. 【Java8新特性】面试官:谈谈Java8中的Stream API有哪些终止操作?

    写在前面 如果你出去面试,面试官问了你关于Java8 Stream API的一些问题,比如:Java8中创建Stream流有哪几种方式?(可以参见:<[Java8新特性]面试官问我:Java8中 ...

  5. [安卓基础] 004.运行app

    运行你的app 这篇课程会教你: 1.如何在设备上运行你的app. 2.如何在模拟器上运行你的app. 当然,在学习之前,你还需要知道: 1.如何使用设备. 2.如何使用模拟器. 3.管理你的项目. ...

  6. [安卓基础] 005.创建一个简单的UI

    *:first-child { margin-top: 0 !important; } body > *:last-child { margin-bottom: 0 !important; } ...

  7. Rocket - util - GenericParameterizedBundle

    https://mp.weixin.qq.com/s/vf0PfjbxQ3Ywjk6tk85SfA   介绍GenericParameterizedBundle的实现.   ​​   1. 基本介绍 ...

  8. Java实现 LeetCode 430 扁平化多级双向链表

    430. 扁平化多级双向链表 您将获得一个双向链表,除了下一个和前一个指针之外,它还有一个子指针,可能指向单独的双向链表.这些子列表可能有一个或多个自己的子项,依此类推,生成多级数据结构,如下面的示例 ...

  9. Java实现 LeetCode 377 组合总和 Ⅳ

    377. 组合总和 Ⅳ 给定一个由正整数组成且不存在重复数字的数组,找出和为给定目标正整数的组合的个数. 示例: nums = [1, 2, 3] target = 4 所有可能的组合为: (1, 1 ...

  10. Java实现 蓝桥杯VIP 算法训练 Hanoi问题

    问题描述 如果将课本上的Hanoi塔问题稍做修改:仍然是给定N只盘子,3根柱子,但是允许每次最多移动相邻的M只盘子(当然移动盘子的数目也可以小于M),最少需要多少次? 例如N=5,M=2时,可以分别将 ...