P9358 题解
不难发现,最开始有 \(n\) 条链,并且由于每个点最多有一个桥,所以我们的交换操作实际上等价于将相邻的两条链断开,然后将它们后半部分交换。并且每个点在路径中的相对位置不变。
于是考虑维护这些链。
有一个很直观的思路就是维护点对 \((i,j)\) 表示最开始第 \(i\) 条链的第 \(j\) 个点在哪条链中,我们需要快速改变它以及它后面点的引索,所以考虑把在一条链中的点对放到一棵以 \(j\) 为键值的 FHQtreap 上并维护每个点所属的 treap 然后操作就变成了分裂之后交换子树以及查询最大值,这个很好维护,可问题是点数是 \(O(nm)\) 级别的。
所以考虑维护三元组表示最开始第 \(i\) 条链上第 \(l\) 到第 \(r\) 个点当前所在的链,不难发现最开始有 \(n\) 个三元组且一次操作最多使一个三元组分裂为 \((x,l,t)\) 与 \((x,t+1,r)\) 故三元组数量为 \(O(n + m)\) 级别。
为了快速检索每个点在那个三元组中,把 \(x\) 相同的三元组放在一个可以支持快速插入删除寻找前驱后继的平衡树中,在平衡树中储存三元组所在的节点的编号即可。
如此我们便在 \(O(n \log n)\) 的时间内解决了问题。
#include<bits/stdc++.h>
#include <ext/pb_ds/assoc_container.hpp>
#include <ext/pb_ds/tree_policy.hpp>
using namespace std;
const int maxn = 5e5+114;
__gnu_pbds::tree< pair<int, int>, __gnu_pbds::null_type, less< pair<int, int> >,__gnu_pbds::rb_tree_tag,__gnu_pbds::tree_order_statistics_node_update > Index[maxn];
//(r,tot)
struct Node{
int l,r,p;
int fa;
int ls,rs;
int val;
}tr[maxn];
int root[maxn];
map<int,int> found;
int tot;
int clone(int l,int r,int p){
tr[++tot].l=l,tr[tot].r=r,tr[tot].p=p,tr[tot].val=rand();
return tot;
}
int merge(int x,int y){
if(!x||!y) return x+y;
if(tr[x].val>tr[y].val){
tr[x].rs=merge(tr[x].rs,y);
tr[tr[x].rs].fa=x;
return x;
}
else{
tr[y].ls=merge(x,tr[y].ls);
tr[tr[y].ls].fa=y;
return y;
}
}
void split(int cur,int x,int &l,int &r){
if(cur==0){
l=r=0;
return ;
}
if(tr[cur].l>x){
r=cur;
split(tr[cur].ls,x,l,tr[cur].ls);
tr[tr[cur].ls].fa=cur;
}
else{
l=cur;
split(tr[cur].rs,x,tr[cur].rs,r);
tr[tr[cur].rs].fa=cur;
}
}
int find_root(int x){//寻找点 x 所在的根
while(tr[x].fa!=0){
x=tr[x].fa;
}
return x;
}
int Ord_split(int x,int pos){//将 (x,pos) 所在的有序段分裂为 [l,x] 与 [x+1,r]
int y = (*Index[pos].lower_bound(make_pair(x,x))).second;
int lt=tr[y].l,rt=tr[y].r,p=tr[y].p;
y=find_root(y);
if(x==rt) return y;
int pos_rt=found[y];
int tr1=0,tr2=0,tr3=0;
split(y,lt-1,tr1,tr2);
split(tr2,lt,tr2,tr3);
int New1=clone(lt,x,p),New2=clone(x+1,rt,p);
found[y]=0;
y=merge(tr1,merge(New1,merge(New2,tr3)));
tr[y].fa=0,found[y]=pos_rt,root[pos_rt]=y;
Index[pos].erase(Index[pos].lower_bound(make_pair(x,x)));
Index[pos].insert(make_pair(x,New1));
Index[pos].insert(make_pair(rt,New2));
return y;
}
int n,m,q;
void build(){
for(int i=1;i<=n;i++){
int y=clone(1,m+1,i);
tr[y].fa=0,found[y]=i,root[i]=y;
Index[i].insert(make_pair(m+1,y));
}
}
int End(int x){
if(tr[x].rs==0) return tr[x].p;
else return End(tr[x].rs);
}
int query(int x){//查询从点 x 开始最后会到那个点
return End(root[x]);
}
void opt(int a,int b){
int x=Ord_split(b,a);
int y=Ord_split(b,a+1);
x=find_root(x);
y=find_root(y);
int x_pos = found[x];
int y_pos = found[y];
int tr1=0,tr2=0,tr3=0,tr4=0;
split(x,b,tr1,tr2);
split(y,b,tr3,tr4);
found[x]=0;
found[y]=0;
x=merge(tr1,tr4);
y=merge(tr3,tr2);
tr[x].fa=0,found[x]=x_pos,root[x_pos]=x;
tr[y].fa=0,found[y]=y_pos,root[y_pos]=y;
}
int main(){
ios::sync_with_stdio(0);
cin.tie(0);
cout.tie(0);
cin>>n>>m>>q;
build();
for(int i=1;i<=q;i++){
int op;
cin>>op;
if(op==1){
int a,b;
cin>>a>>b;
opt(a,b);
}
else{
int a;
cin>>a;
cout<<query(a)<<'\n';
}
}
return 0;
}
P9358 题解的更多相关文章
- 2016 华南师大ACM校赛 SCNUCPC 非官方题解
我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...
- noip2016十连测题解
以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...
- BZOJ-2561-最小生成树 题解(最小割)
2561: 最小生成树(题解) Time Limit: 10 Sec Memory Limit: 128 MBSubmit: 1628 Solved: 786 传送门:http://www.lyd ...
- Codeforces Round #353 (Div. 2) ABCDE 题解 python
Problems # Name A Infinite Sequence standard input/output 1 s, 256 MB x3509 B Restoring P ...
- 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解
题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...
- 2016ACM青岛区域赛题解
A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others) Memory Limit: 65536/65536 K (Jav ...
- poj1399 hoj1037 Direct Visibility 题解 (宽搜)
http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...
- 网络流n题 题解
学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...
- CF100965C题解..
求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...
- JSOI2016R3 瞎BB题解
题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...
随机推荐
- 茴香豆 RAG 平台实操-书生浦语大模型实战营第二期第3节作业
书生浦语大模型实战营第二期第3节作业 本页面包括实战营第二期第三节作业的全部操作步骤.如果需要知道RAG相关知识请访问学习笔记. 作业要求 基础作业 在茴香豆 Web 版中创建自己领域的知识问答助手 ...
- 基于webapi的websocket聊天室(三)
上一篇处理了超长消息的问题.我们的应用到目前为止还是单聊天室,这一篇就要处理的多聊天室的问题. 思路 第一个问题,怎么访问不同聊天室 这个可以采用路由参数来解决.我把路由设计成这样/chat/{roo ...
- 5款.NET开源、免费、功能强大的图表库
LiveCharts2 LiveCharts2是一个.NET开源(MIT License).简单.灵活.交互式且功能强大的.NET图表.地图和仪表,现在几乎可以在任何地方运行如:Maui.Uno Pl ...
- Swoole 源码分析之 epoll 多路复用模块
首发原文链接:Swoole 源码分析之 Http Server 模块 大家好,我是码农先森. 引言 在传统的IO模型中,每个IO操作都需要创建一个单独的线程或进程来处理,这样的操作会导致系统资源的大量 ...
- CSS---鼠标悬浮时逐渐变大样式
.tuijian_2:hover{ transform: scale(1.3); transition: all 1s; }
- 视觉族: 基于Stable Diffusion的免费AI绘画图片生成器工具
视觉族是一款基于Stable Diffusion文生图模型的免费在线AI绘画图片生成器工具,可以使用提示关键词快速生成精美的艺术图片,支持中文提示.无论你是想要创作自己的原创作品,还是想要为你的文字增 ...
- Google,Baidu,Bing三大搜素引擎图片爬虫
Google,Baidu,Bing三大搜素引擎图片爬虫 参考https://mp.weixin.qq.com/s/75QDjRTDCKzuM68L4fg5Lg 这个爬虫由ID为sczhengyabin ...
- 7.13晚考试总结(NOIP模拟14)[队长快跑·影魔·抛硬币]
樱花满地集于我心,楪舞纷飞祈愿相随 前言 终于没有令人头疼的数学了,总感觉这次考试的题目比较良心. 尤其是对于部分分的明细就非常到位(不像上一场的凭感觉给出部分分). 这就令我这种靠部分分暴力的菜鸡选 ...
- c# winfrom DataGridView 动态UI下载功能(内含GIF图) || 循环可变化的集合 数组 datatable 等
Gif演示 分解步骤 1,使用组件DataGridView 2,使用DataSource来控制表格展示的数据来源(注意:来源需要是DataTable类型) 3,需要用到异步线程.如果是不控制数据源的话 ...
- 实现并发新高度:23ai的无锁列值保留
Oracle Database 23ai支持Lock-Free Reservation,中文通常译为"无锁列值保留". 本文将通过3个部分来阐述Lock-Free Reservat ...