【Noip2017Day1T2】时间复杂度 解题报告

【题面】

洛谷P3952

【思路分析】

显然,这是一道模拟题。
所以是模拟的。
我采用的是读入一行处理一行的在线处理。
因为我不会说话所以详情请见代码注释。

【代码】
#include<bits/stdc++.h>
using namespace std;
bool used_[256];//纪录这个字母是否用过
int zhan[200];//栈
int ceng[200],bl[200],cc[200];
//ceng表示当前层自身的次数
//bl表示当前层用的变量
//cc表示当前层包含它的循环体的次数
void work()
{
    int L;
    string st;
    cin>>L>>st;
    string stt;
    getline(cin,stt);
    int numf=0,tou=0;//numf是当前循环层数,tou是栈中元素个数
    int flag=1;//1:Yes;2:No;3:ERR;
    memset(ceng,0,sizeof(ceng));
    memset(used_,0,sizeof(used_));
    memset(zhan,0,sizeof(zhan));
    memset(cc,0,sizeof(cc));
    for  (int i=1;i<=L;i++)
        {
            string stt;
            getline(cin,stt);
            if  (flag==3)
                continue;
            stt+=' ';
            if  (stt[0]=='E')
                {
                    if  (numf==0)//E比F多,不匹配
                        {
                            flag=3;
                            continue;
                        }
                    numf--;
                    if  (ceng[zhan[tou]]!=-1)
                        cc[zhan[tou-1]]=max(cc[zhan[tou-1]],ceng[zhan[tou-1]]+cc[zhan[tou]]);//更新栈顶的父亲的次数
                    used_[bl[zhan[tou]]]=false;//销毁变量
                    tou--;//这些是弹栈顶
                    continue;
                }
            tou++;
            zhan[tou]=i;
            numf++;
            int q=0;
            bool f1=true,f2=true;//true说明是数字,否则说明是n
            int aa1=0,aa2=0;//是数字时数字的大小
            for  (;stt[q]<97||stt[q]>122;q++);
            if  (used_[stt[q]])//变量正在使用中
                {
                    flag=3;
                    continue;
                }
            else
                used_[stt[q]]=true,bl[i]=stt[q];
            for  (;!isdigit(stt[q])&&stt[q]!='n';q++);
                if  (stt[q]=='n')
                    f1=false;
            for  (;isdigit(stt[q]);aa1=aa1*10+stt[q]-48,q++);
            q++;
            for  (;!isdigit(stt[q])&&stt[q]!='n';q++);
                if  (stt[q]=='n')
                    f2=false;
            for  (;isdigit(stt[q]);aa2=aa2*10+stt[q]-48,q++);
            if  (!f1&&!f2)
                ceng[i]=cc[i]=0;//都是n,次数为0
            else
                {
                    if  (f1&&f2)//都是数字,需要比大小
                        {
                            if  (aa1>aa2)
                                ceng[i]=cc[i]=-1;//没有进入
                            else
                                ceng[i]=cc[i]=0;//次数为0
                            continue;
                        }
                    if  (f1)
                        ceng[i]=cc[i]=1;//常数到n 次数为1
                    else
                        ceng[i]=cc[i]=-1; //n到常数,没有进入
                    //-1说明没有进入这层循环
                }
        }
    if  (numf>0)
        flag=3;
    //for  (int i=0;i<=L;i++)	cout<<cc[i]<<' ';
    if  (flag==3)
        {
            printf("ERR\n");
            return;
        }
    int q=0,ans=0;
    for  (;st[q]!='^'&&st[q]!='1';q++);
    if  (st[q]=='^')
        {
            q++;
            for  (;isdigit(st[q]);ans=ans*10+st[q]-48,q++);
            if  (cc[0]!=ans)
                flag=2;
        }
    else
        {
            if  (cc[0]>0)
                flag=2;
        }
    if  (flag==1)
        printf("Yes\n");
    if  (flag==2)
        printf("No\n");
}
int main()
{
    int T;
    cin>>T;
    for  (int i=1;i<=T;i++)
        work();
    return 0;
}
  • 3
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值