Solution -「CF 1056G」Take Metro
\(\mathcal{Description}\)
Link.
有 \(n\) 个站台在一个圆环上,顺时针编号 \(1\sim n\),其中 \(1\sim m\) 号站台只能乘坐顺时针转的环线,其他车站只能乘坐逆时针转的环线。给定起点 \(s\) 和参数 \(t\),运动规则为:
乘坐在 \(s\) 站的环线,坐 \(t\) 站,令 \(s\) 为到达的站点;
令 \(t\leftarrow t-1\),若 \(t>0\),返回第一步。
求 \(s\) 最终的值。
\(3\le n\le10^5\),\(1\le t\le 10^{12}\)。
\(\mathcal{Solution}\)
想要倍增?参数 \(t\) 每时每刻在变化,不可能直接倍增。
但注意到运动是在环上,所以 \(t\) 和 \((t\bmod n)\) 在当前一步运动所达到的效果是等价的,而且 \(n\) 的范围能够接受,我们可以暴力模拟直到 \(t\) 成为 \(n\) 的倍数。
接着再用倍增,我们需要求出从 \(i~(i=1,2,\cdots,n)\) 出发,参数 \(t=n\),运动完成后到达的点。不放令所有点编号 \(-1\) 方便接下来使用 DP,令 \(f(i,j)\) 表示从 \(i\) 出发,参数 \(t=j\),运动完成后到达的点。显然有转移
i&j=0\\
f(i+j,j-1)&i\in[0,m)\land j>0\\
f(i-j,j-1)&i\in[m,n)\land j>0
\end{cases}
\]
其中第一维默认取\(\bmod n\) 意义下的非负值。可见,我们仅需要支持对 \(f(i)\) 这一维状态进行整段的提取和拼接,就能“整体 DP”出 \(f(i+1)\) 的状态。
用可持久化 treap 维护这一过程即可。注意 DP 中提取出的两段区间可能有大面积重叠,需要使用随机合并的方法实现 merge 操作,并且定期重构树并回收掉所有用于持久化的结点。
求出 \(f(i,n)\) 后,对其处理倍增数组即可回答询问。
复杂度 \(\mathcal O(n\log t)\),常数较大。
\(\mathcal{Code}\)
/* Clearink */
#include <cstdio>
#include <cassert>
#include <cstdlib>
#define rep( i, l, r ) for ( int i = l, rpbound##i = r; i <= rpbound##i; ++i )
#define per( i, r, l ) for ( int i = r, rpbound##i = l; i >= rpbound##i; --i )
typedef long long LL;
const int MAXN = 1e5, MAXLG = 39;
int n, m, s, f[MAXN + 5][MAXLG + 5], tf[MAXN + 5];
LL turn;
struct PersistentTreap {
static const int MAXND = 4e7;
int node, val[MAXND + 5], ch[MAXND + 5][2], siz[MAXND + 5];
// nodes's id are 0-based.
PersistentTreap() { srand( 20120712 ); }
inline int crtnd( const int v ) {
int u = node++;
val[u] = v, ch[u][0] = ch[u][1] = -1, siz[u] = 1;
return u;
}
inline void copy( const int u, const int v ) {
val[u] = val[v], ch[u][0] = ch[v][0], ch[u][1] = ch[v][1];
siz[u] = siz[v];
}
inline void pushup( const int u ) {
siz[u] = 1 + ( ~ch[u][0] ? siz[ch[u][0]] : 0 )
+ ( ~ch[u][1] ? siz[ch[u][1]] : 0 );
}
inline bool goleft( const int a, const int b ) {
return rand() % ( a + b ) < a;
}
inline int merge( const int u, const int v ) {
if ( !~u || !~v ) return ~u ? u : v;
int w = crtnd( 0 );
if ( goleft( siz[u], siz[v] ) ) {
copy( w, u ), ch[w][1] = merge( ch[w][1], v );
} else {
copy( w, v ), ch[w][0] = merge( u, ch[w][0] );
}
return pushup( w ), w;
}
inline void rsplit( const int u, const int k, int& x, int& y ) {
if ( !~u ) return void( x = y = -1 );
if ( !k || ( ~ch[u][0] && k <= siz[ch[u][0]] ) ) {
assert( node < MAXND );
copy( y = crtnd( 0 ), u );
rsplit( ch[y][0], k, x, ch[y][0] );
pushup( y );
} else {
assert( node < MAXND );
copy( x = crtnd( 0 ), u );
rsplit( ch[x][1],
k - ( ~ch[u][0] ? siz[ch[u][0]] : 0 ) - 1, ch[x][1], y );
pushup( x );
}
}
inline int rebuild( const int l, const int r, const int* arr ) {
if ( l > r ) return -1;
int mid = l + r >> 1, u = crtnd( arr[mid] );
ch[u][0] = rebuild( l, mid - 1, arr );
ch[u][1] = rebuild( mid + 1, r, arr );
return pushup( u ), u;
}
inline void travel( const int u, int& idx, int* arr ) {
if ( !~u ) return ;
travel( ch[u][0], idx, arr );
arr[idx++] = val[u];
travel( ch[u][1], idx, arr );
}
} trp;
inline int extract( const int rt, int l, int r ) {
l = ( l % n + n ) % n, r = ( r % n + n ) % n;
int x, y, z;
if ( l <= r ) {
trp.rsplit( rt, l, x, y );
assert( trp.siz[y] >= r - l + 1 );
trp.rsplit( y, r - l + 1, y, z );
return y;
} else {
trp.rsplit( rt, r + 1, x, y );
assert( trp.siz[y] >= l - r - 1 );
trp.rsplit( y, l - r - 1, y, z );
return trp.merge( z, x );
}
}
int main() {
scanf( "%d %d %d %lld", &n, &m, &s, &turn ), --s;
for ( ; turn % n; --turn ) {
s = ( s + ( s < m ? turn : -turn ) % n + n ) % n;
}
turn /= n;
int rt = -1;
rep ( i, 0, n - 1 ) rt = trp.merge( rt, trp.crtnd( i ) );
rep ( i, 1, n ) {
rt = trp.merge( extract( rt, i, i + m - 1 ),
extract( rt, m - i, n - i - 1 ) );
if ( !( i % 5000 ) ) {
int tmp = 0;
trp.travel( rt, tmp, tf );
trp.node = 0, rt = trp.rebuild( 0, tmp - 1, tf );
}
}
int tmp = 0;
trp.travel( rt, tmp, tf );
rep ( i, 0, n - 1 ) f[i][0] = tf[i];
for ( int j = 1; 1ll << j <= turn; ++j ) {
rep ( i, 0, n - 1 ) {
f[i][j] = f[f[i][j - 1]][j - 1];
}
}
for ( int j = 39; ~j; --j ) if ( ( turn >> j ) & 1 ) s = f[s][j];
printf( "%d\n", s + 1 );
return 0;
}
Solution -「CF 1056G」Take Metro的更多相关文章
- Solution -「CF 1342E」Placing Rooks
\(\mathcal{Description}\) Link. 在一个 \(n\times n\) 的国际象棋棋盘上摆 \(n\) 个车,求满足: 所有格子都可以被攻击到. 恰好存在 \(k\ ...
- Solution -「CF 1622F」Quadratic Set
\(\mathscr{Description}\) Link. 求 \(S\subseteq\{1,2,\dots,n\}\),使得 \(\prod_{i\in S}i\) 是完全平方数,并最 ...
- Solution -「CF 923F」Public Service
\(\mathscr{Description}\) Link. 给定两棵含 \(n\) 个结点的树 \(T_1=(V_1,E_1),T_2=(V_2,E_2)\),求一个双射 \(\varph ...
- Solution -「CF 923E」Perpetual Subtraction
\(\mathcal{Description}\) Link. 有一个整数 \(x\in[0,n]\),初始时以 \(p_i\) 的概率取值 \(i\).进行 \(m\) 轮变换,每次均匀随机 ...
- Solution -「CF 1586F」Defender of Childhood Dreams
\(\mathcal{Description}\) Link. 定义有向图 \(G=(V,E)\),\(|V|=n\),\(\lang u,v\rang \in E \Leftrightarr ...
- Solution -「CF 1237E」Balanced Binary Search Trees
\(\mathcal{Description}\) Link. 定义棵点权为 \(1\sim n\) 的二叉搜索树 \(T\) 是 好树,当且仅当: 除去最深的所有叶子后,\(T\) 是满的: ...
- Solution -「CF 623E」Transforming Sequence
题目 题意简述 link. 有一个 \(n\) 个元素的集合,你需要进行 \(m\) 次操作.每次操作选择集合的一个非空子集,要求该集合不是已选集合的并的子集.求操作的方案数,对 \(10^9 ...
- Solution -「CF 1023F」Mobile Phone Network
\(\mathcal{Description}\) Link. 有一个 \(n\) 个结点的图,并给定 \(m_1\) 条无向带权黑边,\(m_2\) 条无向无权白边.你需要为每条白边指定边权 ...
- Solution -「CF 599E」Sandy and Nuts
\(\mathcal{Description}\) Link. 指定一棵大小为 \(n\),以 \(1\) 为根的有根树的 \(m\) 对邻接关系与 \(q\) 组 \(\text{LCA}\ ...
随机推荐
- websocket 使用 spring 的service层 ,进而调用里面的 dao层 来操作数据库 ,包括redis、mysql等通用
1.前言 描述一下今天用websocket踩得坑 --->空指针异常! 我想在websocket里面使用service 层的接口,从中获取数据库的一些信息 , 使用 @Autowired 注 ...
- root安装jdk其它用户授权
sudo chmod -R 755 java安装目录 sudo chown -R [username] java安装目录
- Linux防火墙--IPtables企业级配置策略思路
一.防火墙简介 防火墙定义:是通过有机结合各类用于安全管理与筛选的软件和硬件设备,帮助计算机网络于其内.外网之间构建一道相对隔绝的保护屏障,以保护用户资料与信息安全性的一种技术. 防火墙发展应用:最早 ...
- 在asp.net webfrom 中完成用户自定义导出
asp.net原生控件实现自定义列导出功能 自定义列实现 最近负责开发公司内部使用的人事信息化系统时,有一个需求是这样的,需要在页面中可以用户每次导出Excel时自定义需要导出哪些列,经过半天的琢磨和 ...
- Java集合-ArrayList源码分析
目录 1.结构特性 2.构造函数 3.成员变量 4.常用的成员方法 5.底层数组扩容原理 6.序列化原理 7.集合元素排序 8.迭代器的实现 9.总结 1.结构特性 Java ArrayList类使用 ...
- 搭建服务器之文件共享cifs,nfs,samba
cifs: 微软系统中用于网上邻居共享的一个机制,在linux下也可以通过命令mount -t cifs .....来挂载共享的文件目录等. nfs: linux之间的共享文件方式,基于rpc ser ...
- 《手把手教你》系列技巧篇(六十)-java+ selenium自动化测试 - 截图三剑客 -中篇(详细教程)
1.简介 前面我们介绍了Selenium中TakeScreenshot类来截图,得到的图片是浏览器窗口内的截图.有时候,只截浏览器窗口内的图是不够的,而且TakeScreenshot截图只针对浏览器的 ...
- gin框架中的数据解析与绑定
Json数据解析与绑定 客户端传参,后端接收并解析到结构体 func Login(context *gin.Context) { // 声明接收的变量 var login LoginJson // 将 ...
- Maven作用及安装
与传统开发项目相比使用Maven: 1)Maven可以管理jar文件 2)自动下载jar和它的文档,源代码 3)管理jar直接的依赖,a.jar需要b.jar,maven会自动下载b.jar 4)管理 ...
- CentOS升级polkit版本,解决 Linux Polkit 存在权限提升的漏洞 (CVE-2021-4034)
漏洞描述 受影响版本的 pkexec 无法正确处理调用参数计数,最终尝试将环境变量作为命令执行,攻击者可以通过修改环境变量来利用此漏洞,诱使 pkexec 执行任意代码,从而导致将本地权限提升为 ro ...