P1081 [NOIP2012 进步组] 开车观光

一给  金牌会员 | 2024-7-30 08:13:20 | 显示全部楼层 | 阅读模式
打印 上一主题 下一主题

主题 856|帖子 856|积分 2568

思绪:

首先令 \(nxt1_i\) 表示右侧最近的城市间隔(\(id1_i\) 为编号),令 \(nxt2_i\) 表示右侧第二近的城市编号(\(id2_i\) 为编号);可以利用 set 找出离这个城市最近的 \(4\) 个城市(前面两个,后面两个)。
定义:

  • \(f_{i,j}\) 表示从 \(i\) 点出发走 \(2^j\) 轮末了到达的位置。
  • \(dp1_{i,j}\) 表示从 \(i\) 点出发走 \(2^j\) 轮末了 A 走过的间隔。
  • \(dp2_{i,j}\) 表示从 \(i\) 点出发走 \(2^j\) 轮末了 B 走过的间隔。
初始化:

\[f_{i,0} = id1_{id2_i}\]

\[dp1_{i,0} = nxt2_{i}\]

\[dp2_{i,0} = nxt1_{id2_i}\]
状态转移方程为:

\[f_{i,j} = f_{f_{i,j-1},j-1}\]

\[dp1_{i,j} = dp1_{i,j-1} + dp1_{f_{i,j-1},j-1}\]

\[dp2_{i,j} = dp2_{i,j-1} + dp2_{f_{i,j-1},j-1}\]
此时对于询问 \(1\) 和询问 \(2\):

  • 本质上是求出从每个城市出发后 \(A\) 走的间隔与 \(B\) 走的间隔。
  • 那么考虑从高位到低位贪心,即设当前跳到了 \(s\) 点,若 \(dp1_{s,i} + dp2_{s,i} \le x\),可以从 \(s\) 跳到 \(f_{s,i}\),需要令 \(x \gets x - (dp1_{s,i} + dp2_{s,i})\),然后继续遍历 \(i-1\) 位。
  • 因为是 A 先开车,所以 A 可能会在末了一轮竣事后还能再开上一次,需要特判。
时间复杂度为 \(O((N+Q) \log N)\)。
完整代码:

[code]#include#define Add(x,y) (x+y>=mod)?(x+y-mod)x+y)#define lowbit(x) x&(-x)#define pi pair#define pii pair#define iip pair#define ppii pair#define fi first#define se second#define full(l,r,x) for(auto it=l;it!=r;it++) (*it)=x#define Full(a) memset(a,0,sizeof(a))#define open(s1,s2) freopen(s1,"r",stdin),freopen(s2,"w",stdout);using namespace std;typedef double db;typedef unsigned long long ull;typedef long long ll;bool Begin;const ll N=1e5+10,M=18,INF=1e18;inline ll read(){    ll x=0,f=1;    char c=getchar();    while(c'9'){        if(c=='-')          f=-1;        c=getchar();    }    while(c>='0'&&c
回复

使用道具 举报

0 个回复

倒序浏览

快速回复

您需要登录后才可以回帖 登录 or 立即注册

本版积分规则

一给

金牌会员
这个人很懒什么都没写!
快速回复 返回顶部 返回列表