noip模拟21
A 打印
一眼题。
首先一个很简单的思路就是维护一个打印机的优先队列,按照打印机的时间排序。
但是如果现在可用的打印机有很多,你需要找到一个 id 最小的,这样维护就得把所有时间戳小于当前 的打印机全部弹出,统计,再加回来。有 60 分。
然后就能想到把时间戳小于等于当前的和大于当前的打印机分别维护,因为打印序列递增,时间递增,所以每次加进来的打印任务直接弹上次在大于时间戳范围的队头,加入到当前可用的队列中。
当前可用的队列用 id 排序,大于时间戳的队列用时间和 id 双关键字排序。
每次计算完答案把这个打印机加入大于时间戳的队列即可。
点击查看代码
#include<bits/stdc++.h> using namespace std; #define int long long int n,m; const int N=2e5+5; struct node{ int s,t,id; }a[N<<1]; struct printers{ int tim,id; inline bool operator<(const printers &ll) const { // if(tim==ll.tim) return id>ll.id; return id>ll.id; } }; struct pRinters{ int tim,id; inline bool operator<(const pRinters &ll) const { if(tim==ll.tim) return id>ll.id; return tim>ll.tim; } }; priority_queue<printers>q; priority_queue<pRinters>tmp; vector<int>ans[N]; inline bool cmp(node a,node b) { if(a.t==b.t) return a.s<b.s; return a.t<b.t; } void print() { for(int i=1;i<=m;i++) { cout<<ans[i].size(); sort(ans[i].begin(),ans[i].end()); int siz=ans[i].size(); if(siz) cout<<" "; for(int j=0;j<siz-1;j++) cout<<ans[i][j]<<" "; if(siz) cout<<ans[i][siz-1]; cout<<"\n"; } } signed main() { freopen("print.in","r",stdin); freopen("print.out","w",stdout); ios::sync_with_stdio(false); cin.tie(0),cout.tie(0); cin>>n>>m; for(int i=1;i<=n;i++) cin>>a[i].s>>a[i].t,a[i].id=i; sort(a+1,a+1+n,cmp); for(int i=1;i<=m;i++) q.push({0,i}); for(int i=1;i<=n;i++) { while(!tmp.empty()&&tmp.top().tim<=a[i].t) q.push({tmp.top().tim,tmp.top().id}),tmp.pop(); if(!q.empty()) { int tim=q.top().tim,id=q.top().id;q.pop(); ans[id].push_back(a[i].id); tmp.push({a[i].t+a[i].s,id}); } else { int tim=tmp.top().tim,id=tmp.top().id;tmp.pop(); ans[id].push_back(a[i].id); tmp.push({tim+a[i].s,id}); } } print(); }
B 飞船
有一个很一眼的 dp,设 表示到第 个加油站,速度为 的最小花费,转移就从 和 分别转移即可。
然后发现速度其实是很多个 和 的连乘,于是写成指数的形式,并把操作离线,把每个询问当作一个啥都干不了的加油站,然后转移。时间复杂度 左右。
点击查看代码
#pragma GCC optimize(2) #pragma GCC optimize(3) #pragma GCC optimize("Ofast") #include<bits/stdc++.h> using namespace std; #define int long long int n,q; const int N=2e5+5; const double exps=1e-10,inf=1e18; int dis[N],t[N],id[N]; int y; vector<int>A; const int M=31,K=19; double dp[2][32][20]; int nowdis[N],nowt[N],nowid[N]; struct node{ int dis,t,id,ansid; }a[N]; int ansid[N]; inline bool cmp(node a,node b) { return a.dis<b.dis; } double pow2[32],pow3[20]; double ans[N]; int dd[N]; inline double min(double a,double b) { if(a-b>exps) return b; return a; } inline double calc(double dis,int x,int y){ if(dis<exps)return 0.0; if(dis<exps*pow3[y])return 0.0; dis/=pow3[y]; if(dis<exps*pow2[x])return 0.0; dis/=pow2[x]; return dis; } signed main() { // freopen("b.in","r",stdin); freopen("ship.in","r",stdin); freopen("ship.out","w",stdout); scanf("%lld%lld",&n,&q); bool allxIs1=1,allxIs12=1; for(int i=1;i<=n;i++)scanf("%lld%lld%lld",&dis[i],&t[i],&id[i]),allxIs1&=(id[i]==1); if(allxIs1) { while(q--) { scanf("%lld",&y); long double ans=1.0*y; printf("%.20Lf\n",ans); } return 0; } pow2[0]=pow3[0]=1.0; for(int i=1;i<=M;i++) pow2[i]=pow2[i-1]*2.0; for(int i=1;i<=K;i++) pow3[i]=pow3[i-1]*3.0; for(int i=1;i<=n;i++) if(id[i]>1) A.push_back(i); int cc=0; for(int v:A) nowdis[++cc]=dis[v],nowt[cc]=t[v],nowid[cc]=id[v]; for(int i=1;i<=cc;i++) dis[i]=nowdis[i],t[i]=nowt[i],id[i]=nowid[i]; n=cc; int tmp=n; for(int i=1;i<=q;i++) { scanf("%lld",&y); dis[++tmp]=y,t[tmp]=0,id[tmp]=1,ansid[tmp]=i; } n=tmp; for(int i=1;i<=n;i++) a[i].dis=dis[i],a[i].id=id[i],a[i].t=t[i],a[i].ansid=ansid[i]; sort(a+1,a+1+n,cmp); int r=0; for(int i=0;i<=M;i++) for(int j=0;j<=K;j++) dp[0][i][j]=dp[1][i][j]=inf; dp[0][0][0]=0; int _2lim=0,_3lim=0; for(int i=1;i<=n;i++) { double d=(double)(a[i].dis-a[i-1].dis); r^=1; if(a[i].id==2)++_2lim; if(a[i].id==3)++_3lim; if(a[i].id==4)_2lim+=2; int JL=min(_2lim,M-1ll),KL=min(_3lim,K-1ll); for(int j=0;j<=JL;j++) for(int k=0;k<=KL;k++) dp[r][j][k]=inf; for(int j=0;j<=JL;j++) { for(int k=0;k<=KL;k++) { if(a[i].id==2&&j>0&&dp[r^1][j-1][k]!=(double)inf) dp[r][j][k]=min(dp[r][j][k],dp[r^1][j-1][k]+calc(d,j-1,k)+a[i].t); if(a[i].id==3&&k>0&&dp[r^1][j][k-1]!=(double)inf) dp[r][j][k]=min(dp[r][j][k],dp[r^1][j][k-1]+calc(d,j,k-1)+a[i].t); if(a[i].id==4&&j>1&&dp[r^1][j-2][k]!=(double)inf) dp[r][j][k]=min(dp[r][j][k],dp[r^1][j-2][k]+calc(d,j-2,k)+a[i].t); if(dp[r^1][j][k]==(double)inf) continue; dp[r][j][k]=min(dp[r][j][k],dp[r^1][j][k]+calc(d,j,k)); } } if(a[i].ansid) { ans[a[i].ansid]=inf; for(int j=0;j<=JL;j++) { for(int k=0;k<=KL;k++) if(ans[a[i].ansid]-dp[r][j][k]>exps) ans[a[i].ansid]=dp[r][j][k]; } } } for(int i=1;i<=q;i++) printf("%.20lf\n",ans[i]); }
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 在鹅厂做java开发是什么体验
· 百万级群聊的设计实践
· WPF到Web的无缝过渡:英雄联盟客户端的OpenSilver迁移实战
· 永远不要相信用户的输入:从 SQL 注入攻防看输入验证的重要性
· 浏览器原生「磁吸」效果!Anchor Positioning 锚点定位神器解析