当年太菜了啊,连$60$分的暴力都没拿满,只打了一个$30$分的。

考虑到这题最多只会询问到$30W$个点,且整个矩阵会去到$30W\times 30W$,显然不能将所有的点存下来。

对于每一行(除最右侧的数)我们维护一个$splay$,存储该位置的值,考虑到矩阵很大肯定不能全部开下,我们用一个节点存储一个区间(详情见代码)

这样会发现最右侧一列被吃了,所以我们还要维护一个$splay$去存储这一列的数。

对于一组询问$(x,y)$,当$y=m$时,那么显然直接在最右侧的$slpay$上删去某个位置的值,然后丢到这个$splay$的末尾即可。

当$y≠m$时,我们就在第x课splay中将包含有y这个数的区间拎出来,砍成三段(详情见代码),从这个$splay$中删去这个数字,然后重复$y=m$时所做的操作。

这么做的时间复杂度是$O(m\ log\ n+n\ log\ m+q\ log\ n+q\ log\ m)$,常数有点大但反正过了。

代码貌似不短qwq,可能是我的写法比较垃圾

 #include<bits/stdc++.h>
#define M 500005
#define L long long
#define lc(x) ch[x][0]
#define rc(x) ch[x][1]
using namespace std; int ch[M*][]={},siz[M*]={},fa[M*]={},cnt[M*]={};L a[M*]={};
int rt[M]={},rty=,use=;
L n,m,q,numuse;
void pushup(int x){siz[x]=siz[lc(x)]+siz[rc(x)]+cnt[x];}
void rotate(int x,int &k){
int y=fa[x],z=fa[y];
int l=lc(y)!=x,r=l^;
if(y==k) k=x;
else{
if(lc(z)==y) lc(z)=x;
else rc(z)=x;
}
fa[x]=z; fa[y]=x; fa[ch[x][r]]=y;
ch[y][l]=ch[x][r]; ch[x][r]=y;
pushup(y); pushup(x);
}
void splay(int x,int &k){
while(x!=k){
int y=fa[x],z=fa[y];
if(y!=k){
if((lc(z)==y)^(lc(y)==x)) rotate(x,k);
else rotate(y,k);
}
rotate(x,k);
}
} int find(int x,int k){
if(!x) return ;
if(k<=siz[lc(x)]) return find(lc(x),k);
if(k<=siz[lc(x)]+cnt[x]) return x;
return find(rc(x),k-siz[lc(x)]-cnt[x]);
}
void ins(int &x,int k,int id){
if(!x) {x=id; pushup(id); return;}
if(k<=siz[lc(x)]) ins(lc(x),k,id),fa[lc(x)]=x;
else ins(rc(x),k-siz[lc(x)]-cnt[x],id),fa[rc(x)]=x;
pushup(x);
}
void merge(int x,int y,int &rt){
//合并两个splay
if(!x) {rt=y; return;}
if(!y) {rt=x; return;}
rt=x; fa[x]=;
while(rc(x)) x=rc(x);
rc(x)=y; fa[y]=x;
splay(y,rt);
} int query(int x,int y){
//询问x,y位置的值,并且从splay中分离出来
int now=find(rt[x],y);
if(!now) return ;
splay(now,rt[x]);//找出点的位置
if(cnt[now]==) return now;
int lch=lc(now),rch=rc(now);
int cntl=y-siz[lc(now)];
if(cntl-){
use++;
a[use]=a[now];
cnt[use]=cntl-;
lc(use)=lc(now); fa[lc(use)]=use;
lc(now)=use; fa[use]=now;
pushup(use);
}
a[now]+=cntl-; cnt[now]-=cntl-;
if(cnt[now]>){
use++;
a[use]=a[now]+;
cnt[use]=cnt[now]-;
rc(use)=rc(now); fa[rc(use)]=use;
rc(now)=use; fa[use]=now;
pushup(use);
}
cnt[now]=;
pushup(now);
return now;
} int main(){
// freopen("in.txt","r",stdin);
// freopen("out.txt","w",stdout);
cin>>n>>m>>q;
numuse=n*m;
for(L i=;i<=n;i++){
rt[i]=++use;
a[use]=(i-)*m+;
cnt[use]=siz[use]=m-;
a[++use]=i*m; cnt[use]=;
ins(rty,i-,use);
splay(use,rty);
}
while(q--){
int x,y; scanf("%d%d",&x,&y);
int now=query(x,y),outy=;L outnum;
if(now){
outnum=a[now];
merge(lc(now),rc(now),rt[x]);
}else outy=;
now=find(rty,x);
splay(now,rty);
if(outy) outnum=a[now];
merge(lc(now),rc(now),rty);
lc(now)=rc(now)=;
if(outy==){
ins(rt[x],m-,now);
splay(now,rt[x]);
}
a[++use]=outnum; cnt[use]=;
ins(rty,n-,use); splay(use,rty);
printf("%lld\n",outnum);
}
}

【NOIP2017】列队 splay的更多相关文章

  1. Luogu 3960 [NOIP2017] 列队 - splay|线段树

    题解 是我从来没有做过的裂点splay... 看的时候还是很懵逼的QAQ. 把最后一列的$n$个数放在一个平衡树中, 有 $n$ 个点 剩下的$n$行数, 每行都开一个平衡树,开始时每棵树中仅有$1$ ...

  2. 【loj2319】[NOIP2017]列队 Splay(卡过)

    题目描述 给出一个 $n\times m$ 的矩阵,第 $i$ 行第 $j$ 列的数为 $(i-1)\times m+j$ . 现在有 $q$ 次操作,每次操作给出位置 $(x,y)$ ,取出 $(x ...

  3. [NOIP2017]列队 离线+SBT

    [NOIP2017]列队 题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n×m名学生,方阵 ...

  4. 题解[NOIP2017] 列队

    题解[NOIP2017] 列队 题面 解析 看到这题时感觉这个编号很难维护啊? 后来看了lzf大佬的题解才会.. 首先,考虑一个稍微暴力的做法, 维护每一行的前\(m-1\)个人和最后一列的\(n\) ...

  5. [NOIP2017]列队 (Splay)

    题目链接 NOIP2017真的是不按常理出牌: 1.数学题不在Day2T1 2.一道水题一道细节极多的模拟题一道不知道怎么形容的题(小凯的疑惑)(因为我太菜了) 3.3道大火题 当时看到列队这题是毫无 ...

  6. [NOIP2017]列队(线段树/裂点splay)

    考虑n=1的做法,就是支持: 1.在线删一个数 2.在结尾加一个数 3.查询序列的第y个数 用线段树记录区间内被删元素的个数,可以通过线段树上二分快速得解,对于新增的数,用vector记录即可. 对于 ...

  7. Luogu3960 NOIP2017列队(splay/线段树)

    令splay中的一个点表示一段区间,需要使用其中某个点时将区间分裂即可,剩下的都是splay的基本操作了.写的非常丑陋,注意细节.感觉考场上肯定只能靠部分分苟活了.想起来去年因为各种莫名其妙的原因50 ...

  8. NOIP2017列队(phalanx)解题报告

    列队作为NOIP2017最后一道题,其实并不难,只是相对于其它题目,有点小小的工业 首先,这道题我用splay维护的,如果你不会splay,又想学一下splay,可以来这里学一学,接下来步入正题 首先 ...

  9. NOIP2017 列队 题解报告【56行线段树】

    题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n \times mn×m名学生,方阵的行数 ...

随机推荐

  1. 编写可维护的JavaScript 收纳架

    如果你看过Nicolas C.Zakas写过的任何作品,你必须承认他是个不折不扣的天才.也只有天才级的才能写出<JavaScript高级程序设计>让所有的前端攻城师人手一本.Nicolas ...

  2. 2018.07.07 BZOJ2212: Poi2011Tree Rotations(线段树合并)

    2212: [Poi2011]Tree Rotations Time Limit: 20 Sec Memory Limit: 259 MB Description Byteasar the garde ...

  3. 日历时间选择控件---3(支持ie、火狐)

    效果展示:  源代码: <script language=javascript ><!--/* 调用方法:不能用onfocus,要用onclick  <input onclic ...

  4. python3.4用循环往mysql5.7中写数据并输出

    #!/usr/bin/env python # -*- coding:utf-8 -*- # __author__ = "blzhu" """ pyt ...

  5. SPSS—回归—曲线估计方程案例解析

    上一节介绍了线性回归,虽然线性回归能够满足大部分的数据分析的要求,但是,线性回归并不是对所有的问题都适用, 因为有时候自变量和因变量是通过一个已知或未知的非线性函数关系相联系的,如果通过函数转换,将关 ...

  6. Latex中Matlab代码的环境

    需要用到listings宏包 使用方法: 导言区\usepackage{listings}\lstset{language=Matlab}      %代码语言使用的是matlab\lstset{br ...

  7. Java泛型与Restlet客户端

    写一个与restlet服务器通信的客户端类,用于测试通信是否成功,并且进行交互.为了方便其他人使用,于是,写一个通用的方法封装起来,可是中途却放生了一些问题. 按照正常写法,顺序走下来是这样的: pu ...

  8. C++ - explicit和volatile/const的内容

    第一眼见到explicit和volatile可能会一愣一愣的觉得可能是c11或者c14新加的标识符. 其实不是这样,volatile和const两个关键字在C语言的第二个版本KR C的时候就被加入了C ...

  9. Nginx an upstream response is buffered to a temporary file

    1.错误日志:warn:an upstream response is buffered to a temporary file 解决办法:增加fastcgi_buffers 8 4K;     fa ...

  10. Python 爬虫实战—盘搜搜

    近期公司给了个任务:根据关键搜索百度网盘共享文件并下载. 琢磨了几天写下了一段简单的demo代码,后期优化没有处理. 主要的思路:(1)根据关键字爬取盘搜搜的相关信息 (2)解析并获取盘搜搜跳转到百度 ...