https://codeforces.com/gym/102091

2018-2019 ACM-ICPC, Asia Nakhon Pathom Regional Contest

# 题意

有n个柱子。m次询问。

每次询问从x号柱子跳到y号柱子,最多能踩几个柱子。

每次跳跃只能向低的柱子跳,且中间不能有高于起跳点的柱子。

# 思路

化数列为DAG,对于一个柱子u来说,向左跳到能跳的区域中最高的柱子v,我们连边u->v。然后就类似树上的操作。

注意dfs和bfs中都要做好打标记的操作。

 

#include <bits/stdc++.h>
using namespace std;
#define pb push_back
#define fi first
#define se second
#define debug(x) cerr<<#x << " := " << x << endl;
#define bug cerr<<"-----------------------"<<endl;
#define FOR(a, b, c) for(int a = b; a <= c; ++ a)

typedef long long ll;
typedef long double ld;
typedef pair<int, int> pii;
typedef pair<ll, ll> pll;


template<class T> void _R(T &x) { cin >> x; }
void _R(int &x) { scanf("%d", &x); }
void _R(ll &x) { scanf("%lld", &x); }
void _R(double &x) { scanf("%lf", &x); }
void _R(char &x) { scanf(" %c", &x); }
void _R(char *x) { scanf("%s", x); }
void R() {}
template<class T, class... U> void R(T &head, U &... tail) { _R(head); R(tail...); }


template<typename T>
inline T read(T&x){
    x=0;int f=0;char ch=getchar();
    while (ch<'0'||ch>'9') f|=(ch=='-'),ch=getchar();
    while (ch>='0'&&ch<='9') x=x*10+ch-'0',ch=getchar();
    return x=f?-x:x;
}

const int inf = 0x3f3f3f3f;

const int mod = 1e9+7;

/**********showtime************/
            const int maxn = 1e5+9;
            int a[maxn];
            vector<int>mp[maxn];
            vector<int>hi[maxn];

            int mx[maxn<<2];
            void build(int le, int ri, int rt){
                if(le == ri) {
                    mx[rt] = a[le];
                    return;
                }
                int mid = (le + ri) >> 1;
                build(le, mid, rt<<1);
                build(mid+1,ri,rt<<1|1);
                mx[rt] = max(mx[rt<<1], mx[rt<<1|1]);
            }
            int query(int L, int R, int le, int ri, int rt){
                if(le >= L && ri <= R) {
                    return mx[rt];
                }
                int mid = (le + ri) >> 1;
                int res = 0;
                if(mid >= L) res = max(res, query(L, R, le, mid, rt<<1));
                if(mid < R) res = max(res, query(L, R, mid+1, ri, rt<<1|1));
                return res;
            }
            int low[maxn],up[maxn];
            int st[maxn];
            int top = 0;
            int dp[maxn], mdp[maxn];
            int vis[maxn],used[maxn];
            void dfs(int u, int o) {
                vis[u] = true;
                dp[u] = dp[o] + 1;
                mdp[u] = 0;
                for(int v : mp[u]) {
                    if(!vis[v]) dfs(v, u);
                    mdp[u] = max(mdp[u], mdp[v] + 1);
                }
            }
            bool check(int x, int y) {
                if(y <= up[x] && y >= low[x]) return true;
                if(x <= up[y] && x >= low[y]) return true;
                return false;
            }
int main(){
            int n,m;
            scanf("%d%d", &n, &m);
            for(int i=1; i<=n; i++) {
                scanf("%d", &a[i]);
                hi[a[i]].pb(i);
            }

            for(int i=1; i<=n; i++) {
                while(top > 0 && a[st[top]] < a[i]) top--;
                if(top == 0) low[i] = 1;
                else low[i] = st[top] + 1;
                st[++top] = i;
            }

            top = 0;
            for(int i=n; i>=1; i--) {
                while(top > 0 && a[st[top]] < a[i])top--;
                if(top == 0) up[i] = n;
                else up[i] = st[top] - 1;
                st[++top] = i;
            }

            build(1, n, 1);
            int big = query(1, n, 1, n, 1);

            int root = n + 1;
            queue<int>que;
            for(int v : hi[big]) {
                mp[root].pb(v);
                que.push(v);
            }

            while(!que.empty()) {
                int u = que.front();    que.pop();
                int le = low[u], ri = up[u];
                if(le < u) {
                    int mx = query(le, u - 1, 1, n, 1);
                    int id = lower_bound(hi[mx].begin(), hi[mx].end(), le) - hi[mx].begin();

                    for(int i=id; i<hi[mx].size(); i++) {
                        if(hi[mx][i] >= u) break;
                        int v = hi[mx][i];
                        mp[u].pb(v);
                        if(used[v] == 0)
                        {
                            que.push(v);
                            used[v] = 1;
                        }
                    }
                }
                if(u < ri) {
                    int mx = query(u+1, ri, 1, n, 1);
                    int id = lower_bound(hi[mx].begin(), hi[mx].end(), u+1) - hi[mx].begin();
                    for(int i=id; i<hi[mx].size(); i++) {
                        if(hi[mx][i] > ri) break;
                        int v = hi[mx][i];
                        mp[u].pb(v);
                        if(used[v] == 0) {
                            used[v] = 1;
                            que.push(v);
                        }
                    }
                }
            }

            dfs(root, root);

            for(int i=1; i<=m; i++) {
                int x,y;
                scanf("%d%d", &x, &y);
                if(y == 0) {
                    printf("%d\n", mdp[x]);
                }
                else {
                    if(!check(x, y)) puts("0");
                    else printf("%d\n", abs(dp[x] - dp[y]));
                }
            }
            return 0;
}
View Code

相关文章: