不难发现,最开始有 \(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 题解的更多相关文章

  1. 2016 华南师大ACM校赛 SCNUCPC 非官方题解

    我要举报本次校赛出题人的消极出题!!! 官方题解请戳:http://3.scnuacm2015.sinaapp.com/?p=89(其实就是一堆代码没有题解) A. 树链剖分数据结构板题 题目大意:我 ...

  2. noip2016十连测题解

    以下代码为了阅读方便,省去以下头文件: #include <iostream> #include <stdio.h> #include <math.h> #incl ...

  3. BZOJ-2561-最小生成树 题解(最小割)

    2561: 最小生成树(题解) Time Limit: 10 Sec  Memory Limit: 128 MBSubmit: 1628  Solved: 786 传送门:http://www.lyd ...

  4. Codeforces Round #353 (Div. 2) ABCDE 题解 python

    Problems     # Name     A Infinite Sequence standard input/output 1 s, 256 MB    x3509 B Restoring P ...

  5. 哈尔滨理工大学ACM全国邀请赛(网络同步赛)题解

    题目链接 提交连接:http://acm-software.hrbust.edu.cn/problemset.php?page=5 1470-1482 只做出来四道比较水的题目,还需要加强中等题的训练 ...

  6. 2016ACM青岛区域赛题解

    A.Relic Discovery_hdu5982 Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Jav ...

  7. poj1399 hoj1037 Direct Visibility 题解 (宽搜)

    http://poj.org/problem?id=1399 http://acm.hit.edu.cn/hoj/problem/view?id=1037 题意: 在一个最多200*200的minec ...

  8. 网络流n题 题解

    学会了网络流,就经常闲的没事儿刷网络流--于是乎来一发题解. 1. COGS2093 花园的守护之神 题意:给定一个带权无向图,问至少删除多少条边才能使得s-t最短路的长度变长. 用Dijkstra或 ...

  9. CF100965C题解..

    求方程 \[ \begin{array}\\ \sum_{i=1}^n x_i & \equiv & a_1 \pmod{p} \\ \sum_{i=1}^n x_i^2 & ...

  10. JSOI2016R3 瞎BB题解

    题意请看absi大爷的blog http://absi2011.is-programmer.com/posts/200920.html http://absi2011.is-programmer.co ...

随机推荐

  1. go 操作 Excel

    文档地址: https://xuri.me/excelize/zh-hans/ package main import ( "fmt" "github.com/xuri/ ...

  2. centos 文件系统权限

    模板:drwxrwxrwx r表是读 (Read) .w表示写 (Write) .x表示执行 (eXecute) 读.写.运行三项权限可以用数字表示,就是r=4,w=2,x=1, 777就是rwxrw ...

  3. 同时添加多个的远程桌面工具,Windows远程桌面设置多用户同时登录

    Windows Server 版本上的 Windows 远程桌面服务 (RDS) 允许多个用户同时登录. 但是,在标准的Windows桌面版本(例如Windows 10)上,默认情况下,远程桌面是为单 ...

  4. 2023最新nacos的windows 10安装(保姆级)

    目录 前景提要 一.环境整合 构建工具(参考工具部署方式) 二.找到下载位置 1.在百度中找到下载地址.搜索nacos中文官网. 2.双击进入这个网站,看到首页找到下载位置. 3.进入git地址找到如 ...

  5. 4G EPS 中建立 UE 和 MME 之间的 NAS(非接入服务)信令连接

    目录 文章目录 目录 前文列表 建立 NAS(非接入服务)信令连接 前文列表 <4G EPS 中的小区搜索> <4G EPS 中的 PLMN 选择> <4G EPS 中的 ...

  6. 【题解】A18747.眼红的同学

    题目链接:眼红的同学 题干信息很简单,看到数据量之后就不简单了.在数据量小的时候可以使用双层循环暴力的方法来求答案.显然对于这道题而言O(n^2)是完全过不去的. 前置知识: 使用树状数组求逆序对 会 ...

  7. vue xlsx组件 导出的excel表头插入内容

    主要就是sheet_add_dom这个方法, dom是带有table标签元素的dom节点. timeData是个二维数组:[["条件1","条件2"],[&qu ...

  8. 【c++】求解八皇后问题

    为:在8×8格的国际象棋上摆放8个皇后,使其不能互相攻击,即任意两个皇后都不能处于同一行.同一列或同一斜线上,问有多少种摆法.一共92个解 解决思路:一层层回溯,采用深度优先的递归算法. 动态分配的数 ...

  9. jsonp原理详解——终于弄明白了JSONP

    什么是JSONP? 其实网上关于JSONP的讲解有很多,但却千篇一律,而且云里雾里,对于很多刚接触的人来讲理解起来有些困难,着用自己的方式来阐释一下这个问题,看看是否有帮助. 1.一个众所周知的问题, ...

  10. Java 对象的揭秘

    前言 作为一个 Java 程序员,我们在开发者最多的操作要属创建对象了.那么你了解对象多少?它是如何创建?如何存储布局以及如何使用的?本文将对 Java 对象进行揭秘,以及讲解如何使用 JOL 查看对 ...