1 条题解

  • 0
    @ 2026-9-23 23:05:20

    很劣的解唐唐登场!

    考虑 DP,我们暂时先设 DP 状态为第 ii 行第 jj 个洞的右边到达任意终点需要最小跳跃数。记 si,js_{i,j} 为第 ii 行第 jj 个洞的位置。

    那么我们发现,转移时,洞右边的答案和洞左边的答案关系很难考虑,因为从这个洞跳下去只有左边可以做到。所以我们改变 DP 状态。

    设 dpli,jdpl_{i,j} 为第 ii 行第 jj 个洞的左岸到达任意终点需要最小跳跃数,dpri,jdpr_{i,j} 为第 ii 行第 jj 个洞的右岸到达任意终点需要最小跳跃数。

    然后我们开始转移,现在我们要求出 dpli,j,dpri,jdpl_{i,j},dpr_{i,j}。

    一行内不用多说,继承下一个洞的 dpldpl 即可。

    跑到上一行,dpri,jdpr_{i,j} 可以继承上一行中位置在 si,js_{i,j} 至 si,j+1s_{i,j+1} 的洞的 dprdpr,这是一个区间,考虑树状数组维护。

    跑到下一行,首先 dpli,jdpl_{i,j} 可以继承下一行第一个位置大于 si,js_{i,j} 的洞的 dpldpl,其次可以后面再从下一行跳回本行,可以继承本行位置在 si,j,si+1,ids_{i,j},s_{i+1,id} 的洞的 dprdpr,其中 idid 为下一行第一个位置大于 si,js_{i,j} 的洞。发现这还是一个区间,和上面一样。

    于是就做完了,感觉是最劣的做法。感觉全宇宙只有我会写这么劣的东西。

    ::::info[超唐代码]

    #include<iostream>
    #include<cstdio>
    #include<vector>
    #include<queue>
    #include<algorithm>
    // #define int long long
    #define PII pair<int,int>
    #define PIII pair<int,pair<int,int> >
    using namespace std;
    int n,len,q,num[100005],ans[100005],tot;
    vector<int>s[100005],dpl[100005],dpr[100005],c[100005];
    PIII pq[3000005];
    inline void read(int &x){int ret=0,f=0;char ch=getchar();while(!isdigit(ch)){if(ch=='-')f=1;ch=getchar();}while(isdigit(ch)){ret=(ret<<1)+(ret<<3)+(ch^48);ch=getchar();}x=(f?-ret:ret);}
    inline void write(int x){if(x<0)putchar('-'),x=-x;if(x>9)write(x/10);putchar(x%10+48);}
    inline void writeln(int x){write(x),putchar('\n');}
    inline int find(int x,int v){
        int l=0,r=num[x],res=-1;
        while(l<=r){
            int mid=(l+r)/2;
            if(s[x][mid]>=v) res=mid,r=mid-1;
            else l=mid+1;
        }
        return res;
    }
    inline void update(int p,int x,int v){
        while(x<=num[p]) c[p][x]=min(c[p][x],v),x+=(x&(-x));
    }
    inline int queryr(int p,int x,int y){
        int res=1e9;
        while(y>=x){
            if(y-(y&(-y))<x) res=min(res,dpr[p][y]),y--;
            else res=min(res,c[p][y]),y-=(y&(-y));
        }
        return res;
    }
    bool cmp(PIII x,PIII y){
        if(x.first==y.first){
            if(x.second.first==y.second.first) return x.second.second>y.second.second;
            return x.second.first>y.second.first;
        }
        return x.first>y.first;
    }
    signed main(){
        ios::sync_with_stdio(0);cin.tie(0);cout.tie(0);
        read(n);read(len);read(q);
        for(int i=1;i<=n;i++){
            read(num[i]);
            s[i].resize(num[i]+1);dpl[i].resize(num[i]+1);
            dpr[i].resize(num[i]+1);c[i].resize(num[i]+1);
            s[i][0]=0,dpl[i][0]=dpr[i][0]=c[i][0]=1e9;
            for(int j=1;j<=num[i];j++){
                int x;read(x);
                s[i][j]=x,dpl[i][j]=dpr[i][j]=c[i][j]=1e9;
            }
        }
        for(int i=1;i<=n;i++){
            for(int j=0;j<=num[i];j++){
                if(j==num[i]) dpl[i][j]=1,dpr[i][j]=0;
                pq[++tot]=((PIII){s[i][j],{i,j}});
            } 
        }
        sort(pq+1,pq+tot+1,cmp);
        for(int op=1;op<=tot;op++){
            int y=pq[op].first,x=pq[op].second.first,id=pq[op].second.second;
            if(id<num[x]){
                dpr[x][id]=dpl[x][id+1];
                dpl[x][id]=dpl[x][id+1]+1;
            }
            if(x-1>0){
                int iid=find(x-1,y+1);
                if(iid!=-1&&(id==num[x]||s[x][id+1]>s[x-1][iid])){
                    int iiid=find(x-1,s[x][id+1]);
                    if(iiid==-1) iiid=num[x-1];
                    else iiid--;
                    dpr[x][id]=min(dpr[x][id],queryr(x-1,iid,iiid)+1);
                    dpl[x][id]=min(dpl[x][id],dpr[x][id]+1);
                }
            }
            if(x+1<=n){
                int iid=find(x+1,y+1);
                if(iid!=-1){
                    int iiid=find(x,s[x+1][iid]);
                    if(iiid==-1) iiid=num[x];
                    else iiid--;
                    dpl[x][id]=min(dpl[x][id],min(dpl[x+1][iid],queryr(x,id+1,iiid)+1));
                }else if(iid==-1) dpl[x][id]=0;
            }
            if(id!=0) update(x,id,dpr[x][id]);
        }
        for(int i=1;i<=n;i++){
            if(num[i]>0) ans[i]=dpr[i][0];
            else ans[i]=0;
        }
        while(q--){
            int x;read(x);
            writeln(ans[x]);
        }
        return 0;
    }
    

    ::::

    • 1

    [POI 2020/2021 R1] Gra platformowa / 平台游戏

    信息

    ID
    7531
    时间
    1000ms
    内存
    256MiB
    难度
    10
    标签
    递交数
    1
    已通过
    1
    上传者