前言
兩年了。向那段拼搏的時光致敬。
分析
題目鏈接:時間複雜度
題目看似簡單卻陷阱重重,當時的我因爲沒有考慮到回溯的問題只拿到了40分。心痛。
題目自己去看,我先分析一下思路
如果x!=n & y=n —>答案加一。
如果(x=n & y!=n )或(x=C & y=C & x>y)–>錯誤的循環,他下面的循環都無效
其他情況–>答案不變,下面的循環有效
重複的變量出現後他的答案就是ERR
記錄錯誤的循環的層數,等這一層退出後再刪掉記錄。在此期間任何的輸入都試無效的。
如果有常數級的循環我們就從最早的那一層開始記錄,有幾個記錄幾個,到時候用層數F減去他再與ans取最大值。
我們對每一次輸入的 i x y進行分析,就是上面的思路。
代碼先貼上:
#include <cstdio>
#include <iostream>
#include <cstring>
#include <algorithm>
#define N flag_one[1] //把後面的替換成前面的,省事。
using namespace std;
int n;
int T;
int F;//代表循環的深度
int ans;//所得的答案
int true_ans;//真正的答案
int code_status;//0-->yes 1-->no 2-->ERR//其實我只用到了ERR
char every_var;//輸入的變量名
char sstart[50],eend[50];//x y
char tmp_str[20];
bool vis[30];//記錄變量有沒有出現過
char stack[200];//當前狀態有多少個變量
int flag[2];//flag[0]==1-->wrong for !! 0--->true for . flag[1]==x --->F==x wrong
int flag_one[2];//記錄常數級別循環 [1] --> 第幾層 [2] --> 有幾個
int find_true_ans()
{
int ans=0;
int len = strlen(tmp_str);
ans += tmp_str[len-2]-'0';//O()
//if(tmp_str[len-3] != '^' && tmp_str[len-3] != '(')ans += (tmp_str[len-3] - '0')*10;// ( 應該是0回頭改
if(tmp_str[len-3] == '(')return 0;
if(tmp_str[len-3] != '^' && tmp_str[len-3] != '(')ans += (tmp_str[len-3] - '0')*10;// ( 應該是0回頭改
return ans;
}
void init()//初始化
{
scanf("%d",&n);
memset(stack,0,sizeof(stack));
memset(vis,0,sizeof(vis));
code_status=0;
cin>>tmp_str;
true_ans = find_true_ans();
ans = 0;
flag[0] = 0;
flag[1] = 0;
flag_one[0] = 0;
flag_one[1] = 0;
F=0;
}
bool duex(char check)
{
int ans = check - 'a' + 1;
if(vis[ans])return true;
return false;
}
void del()//刪除
{
int ans = stack[F] - 'a' + 1;
vis[ans] = 0;
stack[F] = 0;
F--;
if(flag[1]>F)flag[1] = 0,flag[0] = 0;
if(flag_one[0])N--;
if(flag_one[0]>F)flag_one[1] = 0,flag_one[0] = 0;
}
bool cnm()//比較常數循環是否正確。
{
int a1,b1;
int len_a = strlen(sstart);
int len_b = strlen(eend);
if(len_a == 1)a1 = sstart[0] - '0';
else a1 = (sstart[0] - '0') * 10 + (sstart[1] - '0');
if(len_b == 1)b1 = eend[0] - '0';
else b1 = (eend[0] - '0') * 10 + (eend[1] - '0');
return a1>b1;
}
int main()
{
int i;
scanf("%d", &T);
while(T--)
{
init();
for(i=1;i<=n;i++)
{
char tmp_status;
cin>>tmp_status;
if(tmp_status == 'E'){del();continue;}//wa
if(tmp_status == 'F')
{
F++;
cin>>every_var>>sstart>>eend;
//變量已經重複和出現重複的直接標記跳過
if(duex(every_var)){code_status=2;continue;}
if(code_status == 2 || flag[0])continue;
//比較一下start和end的大小,大到小就錯了
if(sstart[0] != 'n' && eend[0] == 'n')
{
ans = max(ans,F-N);//wawawa
int ascii = every_var - 'a' + 1;//97-122;
stack[F] = every_var;
vis[ascii] = 1;
}
else if((sstart[0] == 'n' && eend[0] != 'n')|| cnm())//have wrong can not enter
{
flag[0] = 1;
flag[1] = F;
ans = max(ans,F-N-1);
}
else
{
if(!flag_one[0])flag_one[0] = F;
N++;
int ascii = every_var - 'a' + 1;//97-122;
stack[F] = every_var;
vis[ascii] = 1;
ans = max(ans,F-N-1);
}
}
}
if(F!=0)code_status = 2;
if(code_status == 2)printf("ERR\n");
else if(ans == true_ans)printf("Yes\n");
else printf("No\n");
}
return 0;
}
總結
我認爲難點就是需要去記錄哪一層開始有錯誤循環和常數循環。其他還好。我太菜了。做出這題比做出機器人搬重物還高興。