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 ...
随机推荐
- Java Number & Math类
java Number类 Java的内置数据类型有byte.int.long.double等. Java 语言为每一个内置数据类型提供了对应的包装类. int对应的包装类为Integer long对应 ...
- Linux下搭建mongDB环境
参考: https://blog.csdn.net/qq_35763837/article/details/79654023 https://www.linuxidc.com/Linux/2016-0 ...
- [批处理教程之Shell]002.Linux 常用命令大全
这一次收集的是比较基础的 Linux 命令,其实 Linux 命令未必每个都要记住,只要在用到时能查阅到需要的命令的用法. 系统信息 *.显示机器的处理器架构(1)arch *.显示机器的处理器架构( ...
- 创建执行线程方式三:实现Callable接口
Callable接口 ① Java 5.0 在 java.util.concurrent 提供了一个新的创建执行 线程的方式:Callable 接口② Callable 接口类似于 Runnable, ...
- 乌云jsonp案例
新浪微博之点击我的链接就登录你的微博(JSONP劫持) 生活处处有惊喜啊!逛逛wooyun都能捡到bug. 测试的时候没关burp,逛乌云的时候抓到一条url: http://login.sina.c ...
- Shellshock漏洞复现
漏洞分析: exp: curl -A "() { :; }; echo; /bin/cat /etc/passwd" http://172.16.20.134:8080/victi ...
- 使用VUE开发用户后台时的动态路由问题、按钮权限问题以及其他页面处理问题
如今前后端分离是大势所趋,笔者虽然是做后台的,但也不得不学学前端的流行框架VUE -_-||| . 为了学习VUE,笔者搭建了一个简单的用户后台,以此来了解VUE的开发思路(注:本项目不用于实际开发, ...
- 【HBase】HBase架构图
- MySQL 高级—— 锁机制
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.锁的概述 1.锁的定义 锁是计算机协调多个进程或线程并发访问某一资源的机制. 在数据库中,除传统的计 ...
- (Java实现) 洛谷 P1091合唱队形
题目描述 NN位同学站成一排,音乐老师要请其中的(N−K)位同学出列,使得剩下的KK位同学排成合唱队形. 合唱队形是指这样的一种队形:设K位同学从左到右依次编号为1,2,-,K1,2,-,K,他们的身 ...