P3952 时间复杂度

毒瘤大模拟题!

看到这种又是字符串又是模拟的题目就很伤,很多的地方都考验细节。

看到这种处理循环的方式是后进先出,自然想到了用栈来模拟。

但是最主要的思路是怎么算复杂度?

其实说白了也简单:一个循环的复杂度 = 这个循环本身的复杂度 + 在里面嵌套的最大的复杂度

这里的每一个循环变量都是不重复的,如果重复直接判ERR。

那么我们就可以用一个循环变量来代表一个循环,利用他们记录一个循环本身的复杂度实际的复杂度

如何计算一个循环的本身时间复杂度?

  • 如果x不是\(n\),y是\(n\),这个循环是\(O(n)\)的。

  • 如果x和y都是\(n\),这个循环是\(O(1)\)的。

  • 如果x是\(n\)而y不是\(n\),那么这个循环不执行。

  • 如果x和y都是数字,比较他们的大小,当且仅当\(x \leq y\)时有\(O(1)\)的复杂度,否则不执行。

这里有一个很重要的思想:如果一个循环不执行,那么我就不去考虑这个循环内的任何时间复杂度!顶多看看会不会有语法错误就好了。

而有一个挺特殊的情况:如果任何循环都不执行的话是\(O(1)\)的。这个在样例已经跟你说了。

维护的时候直接用一个数字来维护,意义是\(n\)的几次方,所以\(O(1)\)用0来代替,不执行的情况我用-1来搞。

ERR总共有3种情况:

  1. F太多。这个在最后看看栈是不是空的就可以了。

  2. E太多。那么这个时候会发生栈下溢,特判解决。

  3. 变量重名。开一个used数组判一下就可以了。

总体来说不难,但是需要你有正确的思路!!!

这个故事告诉我们:写大模拟的时候一定要先想清楚所有的情况再写!

说人话就是:

\[\huge{Think \quad twice, code \quad once!} \]

代码:

#include<cstdio>
#include<cstring>
#include<iostream>
#include<string>
#include<sstream>
#include<stack>
using namespace std;

string str[105];
bool used[30];
int source[30], comp[30];
int id(char x)
{
    return x - 'a' + 1;
}
int to_int(string x)
{
    int len = x.length(), ans = 0;
    for(int i = 0; i < len; i++) ans = ans * 10 + x[i] - '0';
    return ans;
}
int calc(string x, string y)
{
    bool flag1 = (x[0] != 'n'), flag2 = (y[0] != 'n');// is a number
    if(flag1)
    {
        if(flag2)
        {
            int num1 = to_int(x), num_2 = to_int(y);
            if(num1 <= num_2) return 0;
            else return -1;
        }
        else return 1;
    }
    else
    {
        if(flag2) return -1;
        else return 0;
    }
}
int solve(int len, int expected)
{
    memset(used, false, sizeof used);
    memset(source, 0, sizeof source);
    memset(comp, 0, sizeof comp);
    stack<char> sta;
    int ans = 0;
    for(int i = 1; i <= len; i++)
    {
        stringstream ss(str[i]);
        string opt, name, x, y;
        ss >> opt;
        if(opt[0] == 'F')
        {
            ss >> name >> x >> y;
            if(used[id(name[0])]) return 3;// ERR
            used[id(name[0])] = true;
            comp[id(name[0])] = source[id(name[0])] = calc(x, y);
            sta.push(name[0]);
        }
        else if(opt[0] == 'E')
        {
            if(sta.empty()) return 3;// ERR
            char name = sta.top(); sta.pop();
            used[id(name)] = false;
            if(sta.empty())
            {
                ans = std::max(ans, comp[id(name)]);
            }
            else
            {
                if(source[id(sta.top())] != -1) comp[id(sta.top())] = std::max(comp[id(sta.top())], source[id(sta.top())] + comp[id(name)]);
            }
        }
    }
    if(!sta.empty()) return 3;// ERR
    if(ans == expected) return 1;
    else return 2;
}
void print(int res)
{
    if(res == 1) cout << "Yes\n";
    else if(res == 2) cout << "No\n";
    else if(res == 3) cout << "ERR\n";
    else cout << "I AK NOIP!\n";
}
int main()
{
    int T; cin >> T;
    while(T--)
    {
        int len, expected; string temp;
        cin >> len >> temp;
        if(temp[2] == '1') expected = 0;
        else
        {
            stringstream ss(temp.substr(4));
            ss >> expected;
        }
        for(int i = 0; i <= len; i++) getline(cin, str[i]);
        int res = solve(len, expected);
        print(res);
    }
    return 0;
}
posted @ 2018-11-09 11:15  Garen-Wang  阅读(190)  评论(0编辑  收藏  举报