比赛的时候过了两道,第三道超时20分钟过得
A题简单,我用了17分钟才写出来,看了界面熊大大的status,四分钟,直接把我吓傻,看了他的代码才知道,与大大之间的差距有多大:
#include <iostream>
#include <cstdio>
#include <cmath>
#include <cstring>
#define LL long long
#define pir pir <int,int>
#define m_p make_pair
#define mod 1000000007
using namespace std;
int n,a[1005],f[5005];
int main()
{
//ios::sync_with_stdio(false);
//cin.tie(0);
//int T;scanf("%d",&T);
while(scanf("%d",&n)==1){
memset(f,0,sizeof(f));
for(int i=0;i<n;++i){
scanf("%d",a+i);
f[a[i]]++;
}
bool flag=false;
for(int i=0;i<n;++i){
for(int j=i+1;j<n;++j){
f[a[i]]--;
f[a[j]]--;
if(f[a[i]+a[j]]>=1){
flag=true;break;
}
f[a[i]]++;
f[a[j]]++;
}
if(flag)break;
}
if(flag)puts("YES");
else puts("NO");
}
return 0;
}
思路和代码风格都很巧妙,恩,感觉我的代码就是屌丝代码
以下是我的版本(跟大大的代码放在一起简直是献丑了TT):
#include<cstdio>
#include<cstring>
#include<algorithm>
#include<iostream>
#define MAXN 110
#define MAXM 1100
using namespace std;
int n;
struct node{
int value,index;
bool operator<(node other)const{
return value<other.value;
}
}s[MAXN];
int bsearch(int front,int rear,int value){
int mid;
while(front<rear){
mid=(front+rear)>>1;
if(s[mid].value>=value)
rear=mid;
else
front=mid+1;
}
return front;
}
int main(){
while(cin>>n){
for(int i=1;i<=n;i++){
cin>>s[i].value;
s[i].index=i;
}
sort(s+1,s+n+1);
for(int i=1;i<n;i++){
for(int j=i+1;j<=n;j++){
int sub=s[j].value-s[i].value;
int pos=bsearch(1,n,sub);
while(pos<=n&&s[pos].value==sub){
if(s[pos].index!=s[i].index&&s[pos].index!=s[j].index){
cout<<"YES"<<endl;
goto next;
}
pos++;
}
}
}
cout<<"NO"<<endl;
next:
{}
}
return 0;
}
B题我一次AC,一方面是运气比较好,一开始思路就是对的。另一方面不得不说,前几天的组合数学不是白看的。虽然只看了第一章的排列组合,但做这些题的时候明显感觉自己思路清晰了很多。还记得汉舟学长说过的话“要与数学这位老大哥做好朋友”。现在才有点领会到学长的意境了。
具体分类的方法见代码里的注释:
#include<iostream>
#include<algorithm>
#include<cmath>
#include<cstdio>
using namespace std;
int main(){
int n,s,t;
while(cin>>n>>s>>t){
if(s==t){
if(n==1)
cout<<0;
else
cout<<-1;
}
else{
if(s>1&&s<n&&t>1&&t<n&&abs(s-t)>1){//中间不挨着
cout<<2;
}
else if(s>1&&s<n&&t>1&&t<n&&abs(s-t)==1){//中间挨着
cout<<1;
}
else if(s>1&s<n&&(t==1||t==n)&&abs(s-t)>1){//我中间他边上不挨着
cout<<2;
}
else if(s>1&s<n&&(t==1||t==n)&&abs(s-t)==1){//我中间他边上挨着
cout<<1;
}
else if(t>1&t<n&&(s==1||s==n)){//他中间我边上
cout<<1;
}
else if((s==1||s==n)&&(t==1||t==n)){//都在边上
cout<<0;
}
}
cout<<endl;
}
return 0;
}
C题是完全二叉树,complete binary tree 应该是程序员最喜欢的数据结构之一了吧。看见二叉树,而且是完全的,就应该兴奋起来。可惜我手速慢了。而且,代码写的不够清晰,所以导致最后debug的时候很困难,还有对stl不熟,一边写代码一边还要查资料简直不能再这样了。凡是遇到自己都觉得不清晰的代码,就应该重写吧
#include<cstdio>
#include<iostream>
#include<set>
#include<map>
#include<algorithm>
#define LL long long
using namespace std;
set<LL>table;
map<LL,LL>mapp;
set<LL>ans;
LL maxvis;
void init(){
for(LL i=0;i<63;i++){
table.insert(1LL<<i);
mapp[1LL<i]=i;
}
}
void add(LL n){
//cout<<"add"<<n<<endl;
while(n>=0){
ans.insert(n);
n=(n+2)/2-2;
}
}
LL get(LL n){
LL ret=0;
while(n>1){
ret++;
n/=2;
}
return ret;
}
void bfind(LL n){
if(n<0)
return ;
if(n==0LL){
ans.insert(0LL);
return ;
}
if(table.count(n+2)>0){
LL layer=mapp[n+2];
if(layer>=maxvis){
add(n);
maxvis=layer;
}
}
else{
ans.insert(n);
LL cengshu=get(n+1);
LL shangmian=(1LL<<cengshu)-1;//这个地方写成了小于号,调了半天没发现
LL left=(((1LL<<(cengshu-1))<=(n+1-shangmian))?(1LL<<(cengshu-1)):(n+1-shangmian));
LL leftshangmian=shangmian/2+left;
LL right=n-leftshangmian;
bfind(leftshangmian-1);
bfind(right-1);
}
}
int main(){
LL n;
init();
//for(set<LL>::iterator i=table.begin();i!=table.end();i++)
// cout<<*i<<' ';
while(cin>>n){
maxvis=-1;
bfind(n-1);
cout<<ans.size()<<endl;
// for(set<LL>::iterator i=ans.begin();i!=ans.end();i++)
// cout<<*i<<' ';
ans.clear();
}
return 0;
}