【NOIP2017】列队 splay
当年太菜了啊,连$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的更多相关文章
- Luogu 3960 [NOIP2017] 列队 - splay|线段树
题解 是我从来没有做过的裂点splay... 看的时候还是很懵逼的QAQ. 把最后一列的$n$个数放在一个平衡树中, 有 $n$ 个点 剩下的$n$行数, 每行都开一个平衡树,开始时每棵树中仅有$1$ ...
- 【loj2319】[NOIP2017]列队 Splay(卡过)
题目描述 给出一个 $n\times m$ 的矩阵,第 $i$ 行第 $j$ 列的数为 $(i-1)\times m+j$ . 现在有 $q$ 次操作,每次操作给出位置 $(x,y)$ ,取出 $(x ...
- [NOIP2017]列队 离线+SBT
[NOIP2017]列队 题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n×m名学生,方阵 ...
- 题解[NOIP2017] 列队
题解[NOIP2017] 列队 题面 解析 看到这题时感觉这个编号很难维护啊? 后来看了lzf大佬的题解才会.. 首先,考虑一个稍微暴力的做法, 维护每一行的前\(m-1\)个人和最后一列的\(n\) ...
- [NOIP2017]列队 (Splay)
题目链接 NOIP2017真的是不按常理出牌: 1.数学题不在Day2T1 2.一道水题一道细节极多的模拟题一道不知道怎么形容的题(小凯的疑惑)(因为我太菜了) 3.3道大火题 当时看到列队这题是毫无 ...
- [NOIP2017]列队(线段树/裂点splay)
考虑n=1的做法,就是支持: 1.在线删一个数 2.在结尾加一个数 3.查询序列的第y个数 用线段树记录区间内被删元素的个数,可以通过线段树上二分快速得解,对于新增的数,用vector记录即可. 对于 ...
- Luogu3960 NOIP2017列队(splay/线段树)
令splay中的一个点表示一段区间,需要使用其中某个点时将区间分裂即可,剩下的都是splay的基本操作了.写的非常丑陋,注意细节.感觉考场上肯定只能靠部分分苟活了.想起来去年因为各种莫名其妙的原因50 ...
- NOIP2017列队(phalanx)解题报告
列队作为NOIP2017最后一道题,其实并不难,只是相对于其它题目,有点小小的工业 首先,这道题我用splay维护的,如果你不会splay,又想学一下splay,可以来这里学一学,接下来步入正题 首先 ...
- NOIP2017 列队 题解报告【56行线段树】
题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n \times mn×m名学生,方阵的行数 ...
随机推荐
- 编译 link
--generating dsym file change the appropriate one from 'DWARF with dSYM file' to just 'DWARF',This s ...
- python数据类型2
一 文件格式补充 在python3中,除字符串外,所有数据类型在内存中的编码格式都是utf-8,而字符串在内存中的格式是Unicode的格式. 由于Unicode的格式无法存入硬盘中,所以这里还有一种 ...
- 2018.10.09 NOIP模拟 世界杯(图论+set优化)
传送门 貌似是防akakak题? 不是很清楚. 事实上如果两个人没有严格的大小关系,我们给他们两个连一条边. 这样可以构成很多连通块. 而且对于连通块a,ba,ba,b,aia_iai和bjb_jb ...
- 2018.07.01 BZOJ3295: [Cqoi2011]动态逆序对(带修主席树)
3295: [Cqoi2011]动态逆序对 **Time Limit: 10 Sec Memory Limit: 128 MB Description 对于序列A,它的逆序对数定义为满足i<j& ...
- Nginx upstream的5种权重分配方式(转)
出处:http://www.cnblogs.com/funsion/p/4003499.html?utm_source=tuicool 1.轮询(默认) 每个请求按时间顺序逐一分配到不同的后端服务器, ...
- Part 1 - Getting Started(1-3)
https://simpleisbetterthancomplex.com/series/2017/09/04/a-complete-beginners-guide-to-django-part-1. ...
- 【Unity】1.2 HelloWorld--测试桌面和Android游戏能否正常运行
分类:Unity.C#.VS2015 创建日期:2016-03-23 一.简介 这一节先搞一个最简单的Unity游戏,目的是为了验证Unity的桌面游戏开发环境和Android游戏开发环境是否有问题. ...
- java最全的Connection is read-only. Queries leading to data modification are not allowed
Connection is read-only. Queries leading to data modification are not allowed 描述:框架注入时候,配置了事物管理,权限设置 ...
- (转)C#静态方法使用经验浅谈
转自:http://developer.51cto.com/art/200908/147734.htm C#静态方法有什么弊端? 我们在实际的开发过程中会注意到C#静态方法对于我们程序的影响,那么有哪 ...
- 用python做文本情感分析
情感分析就是分析一句话说得是很主观还是客观描述,分析这句话表达的是积极的情绪还是消极的情绪.原理比如这么一句话:“这手机的画面极好,操作也比较流畅.不过拍照真的太烂了!系统也不好.” ① 情感词 要分 ...