第二次上机赛解题报告及标程

  此次上机,起码从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题以上才算比较理想(可能我想多了)……

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值