咕咕的搜尋序列 dfs + 思維
阿新 • • 發佈:2022-05-06
思維
踩坑
1,觀察完整的dfs序,即後序遍歷,以r為子樹的dfs序一定是連續的,且最右邊為節點r。
2,故有等式: 設 該樹的dfs序為 S, 以r為子樹的dfs序的區間為[x, y] 則有 :
S[y] = r, 最右邊為點r
y - x + 1 = size[r] 該區間的長度等於子樹的大小
3,考慮本題: 如果題中給的dfs序有點被刪除了,則沒刪除的點任滿足上述規律,只需忽略被刪除的點即可。 如果不滿足則必不可能,反之......(我也證明不出來--<-<-<@)。
4,莽了一發,發現大部分樣例都能過,說明大體思路是沒有問題滴,繼續考慮細節問題。
5,
hack 資料: 3 5 4 1
即2號節點被刪除了,但是5出現在3 和 4 之間了,顯然不可能。
6,出現這種情況的原因是因為2號節點被刪除了,故上述演算法沒考慮以2號節點為根的子樹。故只需也考慮被刪除的節點即可,被刪除節點也應該滿足以上的式子。
7,資料大於 1e6 記得關閉 cin 同步,儘量用前向星.
#include <bits/stdc++.h> using namespace std; #define endl '\n' #define int long long #define fi first #define se second #define pb push_back #define foa(x, y, z) for(int x = (y), ooo = (z); x <= z; ++x) #define fos(x, y, z) for(int x = (y), ooo = (z); x >= z; --x) #define ckmax(x, y) ((x) < (y) ? (x) = (y), 1 : 0) #define ckmin(x, y) ((x) > (y) ? (x) = (y), 1 : 0) typedef pair<int, int> pii; typedef long long ll; const int mod = 1e9 + 7; const int inf = 0x3f3f3f3f3f3f3f3f; const int N = 1e6 + 10; int n, m; //vector<int> gr[N]; int b[N], p[N]; int flag; int fl[N], fr[N], g[N]; int h[N], nxt[N], v[N], cnt = 0; void add(int x, int y) { v[++cnt] = y, nxt[cnt] = h[x], h[x] = cnt; } void dfs(int r) { fl[r] = inf, fr[r] = -1; g[r] = 0; if(p[r] != 0) { fl[r] = p[r]; fr[r] = p[r]; g[r] = 1; } for(int i = h[r]; i; i = nxt[i]) { int x = v[i]; dfs(x); g[r] += g[x]; ckmin(fl[r], fl[x]); ckmax(fr[r], fr[x]); } if(fr[r] != -1) { if(p[r] && fr[r] != p[r]) flag = 0; if(fr[r] - fl[r] + 1 != g[r]) flag = 0; } } void solve() { // foa(i, 1, n) gr[i].clear(); cin >> n >> m; memset(h, 0, sizeof(int) * (n + 5)); foa(i, 2, n) { int fa; cin >> fa; // gr[fa].pb(i); add(fa, i); } memset(p, 0, sizeof(int) * (n + 5)); foa(i, 1, m) { cin >> b[i]; p[b[i]] = i; } flag = 1; dfs(1); if(flag) cout << "NOT BAD\n"; else cout << "BAD GUGU\n"; } signed main() { ios::sync_with_stdio(false); cin.tie(0); cout.tie(0); int t; cin >> t; while(t--) solve(); return 0; }