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 ...
随机推荐
- poj3613 求经过n条边的最短路 ----矩阵玩出新高度 。
For their physical fitness program, N (2 ≤ N ≤ 1,000,000) cows have decided to run a relay race usin ...
- nodejs链接mysql 中的问题
首先你得对mysql ,有个大概的认识. 比如说:如何安装,使用基本的语法,测试安装是否能成功,以及成功之后简单的对于数据库的,操作(增删改查)... 下面是业务场景:在爬虫过程中,租后需要将信息输出 ...
- 来自AI的Tips——情景智能
来自AI的Tips--情景智能 上一次我们介绍了华为快服务智慧平台是什么,今天我们来侃一侃平台最有代表性的一个流量入口--情景智能(AI Tips). 首先情景智能在哪呢?大家可以拿出自己的华 ...
- ubuntu 基本操作
一 :下载文件操作 wge 下载地址 解压命令: tar
- python爬取页面内容
from selenium import webdriverimport xlwt driver = webdriver.Chrome(r'D:\chromedriver.exe')driver.ma ...
- DQN(Deep Q-learning)入门教程(二)之最优选择
在上一篇博客:DQN(Deep Q-learning)入门教程(一)之强化学习介绍中有三个很重要的函数: 策略:\(\pi(a|s) = P(A_t=a | S_t=s)\) 状态价值函数:\(v_\ ...
- Android系统签名简介
apk的签名,简单说开发者可以通过签名 对应用进行标识和更新.包名在一个设备上是唯一的,这样可以避免被相同包名应用随意覆盖安装.这是一个非常重要的安全功能.系统中的签名文件,也是对系统中应用进行签名, ...
- 02 . Mysql基础操作及增删改查
SQL简介 SQL(Structured Query Language 即结构化查询语言) SQL语言主要用于存取数据.查询数据.更新数据和管理关系数据库系统,SQL语言由IBM开发. SQL语句四大 ...
- js循环语句while,do..while,for
1. while循环 while(循环条件){ 循环体语句块; } 2.do..while循环 do{ 循环体语句块; }while(循环条件) 两者区别:while先判断后执行.循环体语句可能一次都 ...
- 高性能可扩展mysql 笔记(三)Hash分区、RANGE分区、LIST分区
个人博客网:https://wushaopei.github.io/ (你想要这里多有) 一.MySQL分区表操作 1.定义:数据库表分区是数据库基本设计规范之一,分区表在物理上表现为多个文件, ...