此次上机,起码从board上看要比第一次好了许多……虽然距离理想状态还是差了一些……
渣诚写的验题标程都是非STL的,有时间我会放上来……现在的标程STL居多先凑合看下= =
A. Payment
有点后悔把这道题放在第一道,以至于这道唯一和数据结构无关的题目让大多数人煎熬了好久……Codeforces Round #232 (Div. 2) B题改了下题目描述罢了,连数据都是直接从那里拖来的。做法上机时讲过了,不多说。我的代码里用的都是除法,所以只需要int,有些人的代码需要乘法操作,极端数据下会爆int,需要用long long。
#include<cstdio>
using namespace std;
int main()
{
int n,l,r;
while(~scanf("%d%d%d",&n,&l,&r))
puts(n/l>(n-1)/r?"Yes":"No");
}
B. 婚礼车队
不说数据结构是因为实在太明显了,可不是因为用不到……这道题的停车场是个典型的栈。每次判断栈顶是否符合所需编号,如果符合则出栈,否则将下一个元素进栈,依此类推。如果所有元素都已判断过且栈空则符合要求。由于自己太懒了直接扔个STL的,领会一下思想就好。
#include<cstdio>
#include<algorithm>
#include<stack>
using namespace std;
int main()
{
int n,tmp;
stack<int> data,st;
while(~scanf("%d",&n))
{
for(int i=0; i<n; ++i)
{
scanf("%d",&tmp);
data.push(tmp);
}
bool flag=true;
for(int i=n; flag&&i>=1; --i)
{
if(!st.empty()&&st.top()==i)
{
st.pop();
continue;
}
while(!data.empty())
{
st.push(data.top());
data.pop();
if(st.top()==i)
break;
}
if(st.top()!=i)
flag=false;
else
st.pop();
}
puts(flag?"Yes":"No");
while(!data.empty())
data.pop();
while(!st.empty())
st.pop();
}
}
C. TXT Editer
陈题,一开始就认为这道题很好,一直留到上机。一方面可以用双链表来做,简单的移动插入删除。另外还可以用栈来做,拿两个栈,栈口相对,相接处就是光标。光标向左移动就是左栈元素弹出进右栈,反之亦然;插入删除都是对左栈进行的操作。非常巧妙。膜拜下提出此做法的昂神Orz……
先是链表版的,用STL因为我懒= =
//using list
#include<cstdio>
#include<cstring>
#include<list>
using namespace std;
const int MAXN=500005;
list<char> data;
list<char>::iterator it;
char op[MAXN];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",op);
int l=strlen(op);
it=data.end();
for(int i=0; i<l; ++i)
switch(op[i])
{
case 'L':
if(it!=data.begin())
--it;
break;
case 'R':
if(it!=data.end())
++it;
break;
case 'B':
if(it!=data.begin())
it=data.erase(--it);
break;
default:
data.insert(it,op[i]);
}
for(it=data.begin(); it!=data.end(); ++it)
putchar(*it);
putchar('\n');
data.clear();
}
}
然后是用栈做的。
//using stack
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
const int MAXN=500005;
stack<char> p,q;
char op[MAXN];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",op);
int l=strlen(op);
for(int i=0; i<l; ++i)
switch(op[i])
{
case 'L':
if(!p.empty())
{
q.push(p.top());
p.pop();
}
break;
case 'R':
if(!q.empty())
{
p.push(q.top());
q.pop();
}
break;
case 'B':
if(!p.empty())
p.pop();
break;
default:
p.push(op[i]);
}
while(!p.empty())
{
q.push(p.top());
p.pop();
}
while(!q.empty())
{
putchar(q.top());
q.pop();
}
putchar('\n');
}
}
我们注意到用栈做时,最后输出时为保证正序,需要将左栈元素全部弹入右栈,相当于光标移到最左侧,然后再从右栈中依次弹出并输出。太麻烦了,所以把左栈改成双端队列,嗯对还是STL。
//using deque+stack
#include<cstdio>
#include<cstring>
#include<deque>
#include<stack>
using namespace std;
const int MAXN=500005;
deque<char> p;
stack<char> q;
char op[MAXN];
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
scanf("%s",op);
int l=strlen(op);
for(int i=0; i<l; ++i)
switch(op[i])
{
case 'L':
if(!p.empty())
{
q.push(p.back());
p.pop_back();
}
break;
case 'R':
if(!q.empty())
{
p.push_back(q.top());
q.pop();
}
break;
case 'B':
if(!p.empty())
p.pop_back();
break;
default:
p.push_back(op[i]);
}
while(!p.empty())
{
putchar(p.front());
p.pop_front();
}
while(!q.empty())
{
putchar(q.top());
q.pop();
}
putchar('\n');
}
}
D. 表达式计算
陈题,书上有几乎所有的代码。我们严重怀疑当年的出题人在出数据的时候,代码里使用的是书上的float,所以这道题把float改成double的会WA……嗯对数据里有精度问题,我们一开始也没想到,说声sorry。其他的不多讲了。
#include<cstdio>
using namespace std;
const struct
{
char ch;
int pri;
} lpri[7]= {{'=',0},{'(',1},{'*',5},{'/',5},{'+',3},{'-',3},{')',6}},
rpri[7]= {{'=',0},{'(',6},{'*',4},{'/',4},{'+',2},{'-',2},{')',1}};
int leftpri(char op)
{
for(int i=0; i<7; i++)
if(lpri[i].ch==op)
return lpri[i].pri;
}
int rightpri(char op)
{
for(int i=0; i<7; i++)
if(rpri[i].ch==op)
return rpri[i].pri;
}
bool InOp(char ch)
{
return ch=='('||ch==')'||ch=='+'||ch=='-'||ch=='*'||ch=='/';
}
int Precede(char op1,char op2)
{
if(leftpri(op1)==rightpri(op2))
return 0;
if(leftpri(op1)<rightpri(op2))
return -1;
return 1;
}
void trans(char *exp,char postexp[])
{
struct
{
char data[100];
int top;
} op;
int i=0;
op.top=0;
op.data[op.top]='=';
while(*exp!='\0')
{
if(!InOp(*exp))
{
while(*exp>='0'&&*exp<='9')
postexp[i++]=*(exp++);
postexp[i++]='#';
}
else
switch(Precede(op.data[op.top],*exp))
{
case -1:
op.data[++op.top]=*(exp++);
break;
case 0:
--op.top;
++exp;
break;
case 1:
postexp[i++]=op.data[op.top--];
break;
}
}
while(op.data[op.top]!='=')
postexp[i++]=op.data[op.top--];
postexp[i]='\0';
}
int compvalue(char *postexp)
{
struct
{
float data[100];
int top;
} st;
float d,a,b,c;
st.top=-1;
while(*postexp!='\0')
{
switch(*postexp)
{
case '+':
a=st.data[st.top--];
b=st.data[st.top--];
c=a+b;
st.data[++st.top]=c;
break;
case '-':
a=st.data[st.top--];
b=st.data[st.top--];
c=b-a;
st.data[++st.top]=c;
break;
case '*':
a=st.data[st.top--];
b=st.data[st.top--];
c=a*b;
st.data[++st.top]=c;
break;
case '/':
a=st.data[st.top--];
b=st.data[st.top--];
c=b/a;
st.data[++st.top]=c;
break;
default:
d=0;
while(*postexp>='0'&&*postexp<='9')
d=d*10+*(postexp++)-'0';
st.data[++st.top]=d;
break;
}
++postexp;
}
return st.data[st.top];
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char exp[100],postexp[100];
scanf("%s",exp);
trans(exp,postexp);
printf("%s\n%d\n",postexp,compvalue(postexp));
}
}
E. Arthur爱打羽毛球
裸得不能再裸的队列。只要注意取出特定羽毛球的过程中,队头弹出编号,不是所要的,就再弹进队尾,直到找到特定编号或者转了一个圈就结束。
#include<cstdio>
#include<queue>
using namespace std;
int main()
{
int n,m,k;
char op[10];
queue<int> q;
while(~scanf("%d%d",&n,&m))
{
while(m--)
{
scanf("%s",op);
switch(op[0])
{
case 'P':
scanf("%d",&k);
if(q.size()<n)
puts("JUSTME");
else
{
q.pop();
puts("OOPS");
}
q.push(k);
break;
case 'S':
scanf("%d",&k);
for(int i=0; i<q.size(); ++i)
{
if(q.front()==k)
break;
q.push(q.front());
q.pop();
}
if(q.front()==k)
{
puts("GOTIT");
q.pop();
}
else
puts("WHERE");
break;
case 'R':
if(q.empty())
puts("NONE");
else
{
printf("%d\n",q.front());
q.pop();
}
break;
}
}
while(!q.empty())
q.pop();
}
}
F. 括号匹配
书上例题的加强版。一种括号变成三种罢了,左括号进栈,右括号判断是否和栈顶匹配,很简单。放两个版本的标程。
#include<cstdio>
#include<cstdlib>
#include<cstring>
using namespace std;
struct SqStack
{
char data[105];
int top;
};
void InitStack(SqStack *&s)
{
s=(SqStack *)malloc(sizeof(SqStack));
s->top=-1;
}
void Push(SqStack *&s,char e)
{
s->data[++s->top]=e;
}
void Pop(SqStack *&s,char &e)
{
e=s->data[s->top--];
}
bool GetTop(SqStack *&s,char &e)
{
if(s->top==-1)
return false;
e=s->data[s->top];
return true;
}
int main()
{
int t;
scanf("%d",&t);
while(t--)
{
char str[105],e;
scanf("%s",str);
bool match=true;
SqStack *s;
InitStack(s);
int l=strlen(str);
for(int i=0; match&&i<l; ++i)
switch(str[i])
{
case '(':
case '[':
case '{':
Push(s,str[i]);
break;
case ')':
case ']':
case '}':
if(GetTop(s,e)&&((e=='('&&str[i]==')')||(e=='['&&str[i]==']')||(e=='{'&&str[i]=='}')))
Pop(s,e);
else
match=false;
break;
}
if(s->top!=-1)
match=false;
free(s);
puts(match?"Yes":"No");
}
}
#include<cstdio>
#include<cstring>
#include<stack>
using namespace std;
int main()
{
int t;
char str[100];
stack<char> s;
scanf("%d",&t);
while(t--)
{
scanf("%s",str);
bool match=true;
int l=strlen(str);
for(int i=0; match&&i<l; ++i)
switch(str[i])
{
case '(':
case '[':
case '{':
s.push(str[i]);
break;
case ')':
case ']':
case '}':
if(!s.empty()&&((s.top()=='('&&str[i]==')')||(s.top()=='['&&str[i]==']')||(s.top()=='{'&&str[i]=='}')))
s.pop();
else
match=false;
break;
}
if(!s.empty())
match=false;
puts(match?"Yes":"No");
while(!s.empty())
s.pop();
}
}
G. 天马's wish
陈题,和F题无本质区别。注意Holmes虽然“通杀”但只是女性通杀,不是男女通杀……题干里已经说了他是男性Orz,给你们的想象力跪了……
#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<cctype>
using namespace std;
const int MAXN=100005;
struct SqStack
{
char data[MAXN];
int top;
};
void InitStack(SqStack *&s)
{
s=(SqStack *)malloc(sizeof(SqStack));
s->top=-1;
}
void Push(SqStack *&s,char e)
{
s->data[++s->top]=e;
}
void Pop(SqStack *&s,char &e)
{
e=s->data[s->top--];
}
bool GetTop(SqStack *&s,char &e)
{
if(s->top==-1)
return false;
e=s->data[s->top];
return true;
}
int main()
{
char str[MAXN],e;
while(~scanf("%s",str))
{
int l=strlen(str)-2;
SqStack *t;
InitStack(t);
for(int i=1; i<=l; i++)
if(GetTop(t,e))
{
if((str[i]!='%'&&e!='%')&&abs(e-str[i])=='a'-'A')
Pop(t,e);
else if(str[i]=='%'&&islower(e))
Pop(t,e);
else if(e=='%'&&islower(str[i]))
Pop(t,e);
else
Push(t,str[i]);
}
else
Push(t,str[i]);
puts(t->top==-1?"Yes":"No");
}
}
#include<cstdio>
#include<cstring>
#include<cmath>
#include<cctype>
#include<stack>
using namespace std;
const int MAXN=100005;
int main()
{
char str[MAXN];
stack<char> s;
while(~scanf("%s",str))
{
int l=strlen(str)-2;
for(int i=1; i<=l; i++)
if(!s.empty())
{
if((str[i]!='%'&&s.top()!='%')&&abs(s.top()-str[i])=='a'-'A')
s.pop();
else if(str[i]=='%'&&islower(s.top()))
s.pop();
else if(s.top()=='%'&&islower(str[i]))
s.pop();
else
s.push(str[i]);
}
else
s.push(str[i]);
puts(s.empty()?"Yes":"No");
while(!s.empty())
s.pop();
}
}
说实话这次的题没啥激动人心的……大都是数据结构的基础操作,过3题以上才算比较理想(可能我想多了)……