1. 程式人生 > >luoguP3952 [NOIP2017]時間複雜度 模擬

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]$為止

更新的法則分四類討論

然後剩下地看程式碼吧

 

關於輸入

過載一個輸入就可以了...

// luogu-judger-enable-o2
#include <cstdio>
#include <cstring>
#include <iostream>
using namespace std;

#define debug printf("passing %d Lines\n", __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\n"); continue; } int V = Solve(0); if(V != E) printf("No\n"); else printf("Yes\n"); } return 0; }