F

void solve() {
    int n; cin >> n;
    vector<pair<int, int>> a(n);
    for(int i = 0;i < n; i ++){
        cin >> a[i].first;
        a[i].second = i + 1;
    }
    sort(a.begin(), a.end());
    int ans = 0, l = n, r = -1;
    for(int i = 0;i < n; i++){
        l = min(l, a[i].second);
        r = max(r, a[i].second);
        if(a[i].first == r - l + 1) ans ++;
    }
    cout << ans << "\n";
}

G

void solve() {
    int n; cin >> n;
    vector<vector<int>> adj(n+1);
    for(int i = 1;i < n; i++){
        int u, v; cin >> u >> v;
        adj[u].push_back(v);
        adj[v].push_back(u);
    }
    vector<int> p(n+1);
    vector<bool> vis(n+1);
    for(int i = 1;i <= n; i++) cin >> p[i];
    int ans = 0, x = p[1], y = p[1], z = p[1];//z表示上一个路径的最后一个结点,x表示z的父节点,y表示上一条路径的另一端最外面的结点,
    vis[p[1]] = true;
    function<void(int, int, int)> dfs = [&](int v, int parent, int flag){
        if(ans > n) return ;//不会超过n个点
        if(vis[p[ans]]) return ;//访问过的直接退出,实际上好像不会遇到这种情况吧?
        if(p[ans] == v){//找到目标节点的位置p[ans],这里的ans其实等价于外面的i,p[ans]=p[i]
            vis[v] = true;//找到了就标记
            vis[parent] = true;//路径的过程也标记
            if(flag == 0)//更新链尾的父节点,flag=1的话就是链首了,我们不管他,让他的链首的父节点等于他本身
            x = parent;
            return ;
        }
        for(auto &u : adj[v]){
            if(u != parent){
                if(!vis[u]) dfs(u, v, flag);//没访问过的点继续访问,知道找出目标节点p[i],也就是p[ans]
            }
        }
        if(vis[v]) vis[parent] = true;//和上面一样,将最短路径的所有点都进行标记
    };
    bool ok = true;
    for(int i = 1;i <= n; i++){
        ans ++;
        if(vis[p[i]]) continue;//标记过的点说明在之前的路径上,跳过
        dfs(z, x, 0);//继续从上一条路径的末端继续遍历查询p[i]的点是否存在
        if(vis[p[i]]) z = p[i];//存在就更新上一条路径的链尾
        if(!vis[p[i]]){
            dfs(y, y, 1);//不存在就对链首遍历
            y = p[i];//有的话就更新链首
        }
        if(!vis[p[i]]){//没有的话后面也不会有了,直接退出
            ok = false;//减去当前循环的多加的一个1
            break;
        }
    }
    if(!ok) ans --;
    cout << ans << "\n";
    /*时间复杂度也算是相当于O(n)了吧,标记过的点就不访问了*/
}