WA on test#4,6,10,原因不明
如果我 assert 的是对的,那没有 loop 0 或则 loop 负数,就是 loop 之后的表达是一定是正的。
#include<algorithm>
#include<iostream>
#include<cstring>
#include<cstdio>
#include<cmath>
using namespace std;
typedef long long ll;
inline int gn(char c){return c-'a'+1;}
const int MAXN=2e6+5,INF=0x3f3f3f3f;
int n;string s[MAXN];
int nxt[MAXN],pre[MAXN];ll val[30];
int d[MAXN],lst[MAXN];
inline void read(){
cin>>s[n=0];
for(int d=1;d;){cin>>s[++n];if(s[n]=="loop")d++;else if(s[n]=="end")d--;}n--;
for(int i=n,d=0;i>=1;i--) // nxt 表示后一个匹配的 end
if(s[i]=="end")lst[++d]=i;
else if(s[i]=="loop")d--;
else nxt[i]=lst[d];
for(int i=1,p=0;i<=n;i++) // 处理 continue 和 break
if(s[i]=="loop")p=i;
else if(s[i]=="continue"){d[i]++;d[nxt[i]]--;i=nxt[i];}
else if(s[i]=="break"){d[p]++;d[p+2]--;d[i]++;d[nxt[i]+1]--;i=nxt[i];}
int tot=0;
for(int i=1;i<=n;i++)if(!(d[i]+=d[i-1]))s[++tot]=s[i];
n=tot;memset(lst,0,n+1<<2);
for(int i=1,d=0;i<=n;i++) // pre 表示 end 匹配的 loop
if(s[i]=="loop")lst[++d]=i;
else if(s[i]=="end")pre[i]=lst[d--];
}
const int BASE=10;
inline ll calc(string s){
int l=s.size(),w=INF,p=-1;
if(!l)return 0;
for(int i=l-1,d=0;~i;i--){
if(s[i]==')')d+=BASE;else if(s[i]=='(')d-=BASE;
int t=INF;
if(s[i]=='+'||s[i]=='-')t=d;
else if(s[i]=='*'||s[i]=='/')t=d+1;
if(t<w){w=t;p=i;}
}
if(!~p){
ll num=0;for(char c:s)
if(isdigit(c))num=num*10+(c^0x30);
else if(islower(c))return val[gn(c)];
return num;
}
ll ls=calc(s.substr(0,p)),rs=calc(s.substr(p+1));
if(s[p]=='+')return ls+rs;
if(s[p]=='-')return ls-rs;
if(s[p]=='*')return ls*rs;
return ls/rs;
}
int runT[MAXN]; // runT[i] 当 s[i]=="loop" 时表示当前循环的剩余次数
int main(){
read();
for(int i=1;i<=n;i++){
if(s[i]=="loop"){runT[i]=calc(s[i+1]);i++;}
else if(s[i]=="end"){
if(runT[pre[i]]>1){runT[pre[i]]--;i=pre[i]+1;}
}else if(s[i]=="write"){printf("%lld\n",calc(s[i+1]));i++;}
else val[gn(s[i][0])]=calc(s[i].substr(2));
}
return 0;
}