1 条题解
-
0
很劣的解唐唐登场!
考虑 DP,我们暂时先设 DP 状态为第 行第 个洞的右边到达任意终点需要最小跳跃数。记 为第 行第 个洞的位置。
那么我们发现,转移时,洞右边的答案和洞左边的答案关系很难考虑,因为从这个洞跳下去只有左边可以做到。所以我们改变 DP 状态。
设 为第 行第 个洞的左岸到达任意终点需要最小跳跃数, 为第 行第 个洞的右岸到达任意终点需要最小跳跃数。
然后我们开始转移,现在我们要求出 。
一行内不用多说,继承下一个洞的 即可。
跑到上一行, 可以继承上一行中位置在 至 的洞的 ,这是一个区间,考虑树状数组维护。
跑到下一行,首先 可以继承下一行第一个位置大于 的洞的 ,其次可以后面再从下一行跳回本行,可以继承本行位置在 的洞的 ,其中 为下一行第一个位置大于 的洞。发现这还是一个区间,和上面一样。
于是就做完了,感觉是最劣的做法。感觉全宇宙只有我会写这么劣的东西。
::::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
信息
- ID
- 7531
- 时间
- 1000ms
- 内存
- 256MiB
- 难度
- 10
- 标签
- 递交数
- 1
- 已通过
- 1
- 上传者