luoguP3952 [NOIP2017]时间复杂度 模拟

原本只是想看下多久能码完时间复杂度

然后在30min内就码完了,然后一A了????

首先,这题完全可以离线做

我们先把所有的操作读完,判断合不合法之后,再去判断和标准答案的关系

具体而言

把所有的操作读完之后

对于$F$操作,我们存下这个操作对应的$E$操作,循环范围$[L, R]$以及循环变量

对于$E$操作,我们存下这个操作对应的循环变量

我们记$F$操作对应的$E$操作为$match[i]$

我们可以从左往右对于每一个$E$操作暴力寻找其对应的$F$操作

然后判断一下合不合法,十分好写

之后只要得出正确答案就行了

这也十分好办,定义$Solve(i)$表示以$i$为开端的循环体的循环层数

如果$p$也是一个$F$操作,那么我们用$Solve(p)$更新$Solve(i)$后,令$p = match[p] + 1$

直到$p = match[i]$为止

更新的法则分四类讨论

然后剩下地看代码吧

关于输入

重载一个输入就可以了...

#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define debug printf("passing %d Lines
", __LINE__);

#define gc getchar
inline int read() {
    int p = 0, w = 1; char c = gc();
    while(c > '9' || c < '0') { 
        if(c == '-') w = -1; 
        if(c == 'n') return 101;
        c = gc(); 
    }
    while(c >= '0' && c <= '9') p = p * 10 + c - '0', c = gc();
    return p * w;
}

const int sid = 505;

char s[sid];
bool ex[sid], use[sid];
int top, st[sid], mat[sid];
int L[sid], R[sid], let[sid];

int Solve(int o) {
    int ret = 0;
    int i = o + 1;
    while(i != mat[o]) {
        if(L[i] <= 100 && R[i] <= 100 && L[i] <= R[i]) ret = max(ret, Solve(i));
        if(L[i] <= 100 && R[i] > 100) ret = max(ret, Solve(i) + 1);
        if(L[i] > 100 && R[i] > 100) ret = max(ret, Solve(i));
        i = mat[i] + 1;
    }
    return ret;
}

int main() {
    int t = read();
    while(t --) {
        
        memset(ex, 0, sizeof(ex));
        memset(use, 0, sizeof(use));
        memset(mat, 0, sizeof(mat));
        
        int T = read(), E = read();
        if(E > 100) E = read();
        else E = 0;
        
        top = 0; st[0] = 1;
        while(T --) {
            int x, y;
            scanf("%s", s + 1);
            if(s[1] == 'F') {
                scanf("%s", s + 1);
                int x = read(), y = read();
                st[++ top] = 1;  L[top] = x;
                R[top] = y; let[top] = s[1];
            }
            else st[++ top] = 2;
        }
        st[++ top] = 2;
            
        bool RE = 0;
        for(int i = 0; i <= top; i ++)
        if(st[i] == 2) {
            int pos = -1;
            for(int j = i; ~j; j --)
            if(st[j] == 1 && !use[j]) { pos = j; break; }
            if(pos == -1) { RE = 1; continue; }
            mat[i] = pos; mat[pos] = i;
            let[i] = let[pos]; use[pos] = 1;
        }
        
        for(int i = 0; i <= top; i ++)
            if(i != top && !mat[i]) RE = 1;
        
        for(int i = 0; i <= top; i ++) {
            if(st[i] == 1) {
                if(ex[let[i]]) RE = 1;
                ex[let[i]] = 1;
            }
            else ex[let[i]] = 0;
        }
            
        if(RE) {
            printf("ERR
");
            continue;
        }
    
        int V = Solve(0);
        if(V != E) printf("No
");
        else printf("Yes
");
        
    }
    return 0;
}
原文地址:https://www.cnblogs.com/reverymoon/p/9928249.html