[NOIP2017]列队 线段树
题解:
之前写的splay,,,然而一直没调出来,我感觉是某个细节想错了,,然而已经重构4次代码不想再写splay了。于是今天尝试了线段树的解法。
首先因为每次出列之后的变化都是将当前行左移,然后将最后一列上移,所以最后一列不适合和其他的行放在一起处理。
因此对于每行的前m - 1位开一棵线段树,对于最后一列开一棵线段树。
但是因为空间开销过大无法承受,因此考虑动态开点。一开始每棵线段树内只有一个节点,这个节点代表了当前行1 ~ m - 1的所有节点。
如果我们要从中删除一个节点,就跟普通线段树类似的向下遍历找到单点,然后修改权值为0,并且同步修改这条链上的节点数总和。跟普通线段树不同的是,动态开点需要在函数的最开头判断这个节点是否存在,如果不存在,就建出这个节点,并给这个节点加上一些基本的信息,然后继续向下遍历。
如果我们要添加一个节点到树中,那么我们就直接加在这棵树所有已经存在的叶子节点的后面那个叶子节点处即可。即下图。(虚线表示省略的节点)
同时维护所有线段树即可,注意细节。
#include<bits/stdc++.h>
using namespace std;
#define R register int
#define AC 301000
#define ac 8000000
#define LL long long
#define D printf("line in %d\n", __LINE__); int n, m, q, w, cnt, now;
int root[AC], tree[ac], ls[ac], rs[ac], pos[ac];
LL id[ac], go;//id[ac]要开ac啊,,,,
//对于
inline int read()
{
int x = ;char c = getchar();
while(c > '' || c < '') c = getchar();
while(c >= '' && c <= '') x = x * + c - '', c = getchar();
return x;
} inline int cal(int l, int r)
{
if(now <= n)
{
if(r <= m - ) return r - l + ;
else if(l <= m - ) return (m - ) - l + ;
else return ;
}
else
{
if(r <= n) return r - l + ;
else if(l <= n) return n - l + ;
else return ;
}
} void kth(int &x, int l, int r)//当前节点,当前区间
{
if(!x) x = ++ cnt, tree[x] = cal(l, r);//第一次开出来自然是满的
if(l == r)
{
tree[x] = ;
if(!id[x]) go = (now <= n) ? (LL)(now - ) * (LL)m + l : (LL)m * (LL)l;//如果这个点没有被赋过值,那么就应该是原来的编号
else go = id[x]; //编号爆ll,,,
return ;
}
else
{
-- tree[x];//删除一个节点
int mid = (l + r) >> ;
int tmp = ls[x] ? tree[ls[x]] : cal(l, mid);//获取左边的节点个数
if(w <= tmp) kth(ls[x], l, mid);
else w -= tmp, kth(rs[x], mid + , r);
}
} void ins(int &x, int l, int r)
{
if(!x) x = ++ cnt, tree[x] = cal(l, r);
if(l == r) {tree[x] = , id[x] = go; return ;}
int mid = (l + r) >> ;
++ tree[x];//加入一个节点
if(w <= mid) ins(ls[x], l, mid);//因为已经钦定了位置
else ins(rs[x], mid + , r);//不然去右边
} void pre()
{
n = read(), m = read(), q = read();
for(R i = ; i <= n; i ++) root[i] = ++cnt, tree[cnt] = m - ;
root[n + ] = ++cnt, tree[cnt] = n;//给最后一列单独开一个
} void work()
{
int a, b;LL tmp;
for(R i = ; i <= q; i ++)
{
a = read(), b = read();
if(b < m)
{
now = a, w = b;
kth(root[now], , m + q);//对于维护行的线段树,边界应该是m + q吧
w = a, now = n + , tmp = go;//记录出来的人
printf("%lld\n", tmp);
kth(root[now], , n + q);//从最后一列中取人,
now = a, ++ pos[now], w = m - + pos[now];
ins(root[now], , m + q);
now = n + , ++ pos[now], w = n + pos[now], go = tmp;//把出来的人放在最后一列的最后一个
ins(root[now], , n + q);
}
else
{
now = n + , w = a;
kth(root[now], , n + q);
printf("%lld\n", go);
++ pos[now], w = n + pos[now];//直接算出来应该放在哪个位置
ins(root[now], , n + q);
}
}
} int main()
{
// freopen("in.in", "r", stdin);
pre();
work();
// fclose(stdin);
return ;
}
[NOIP2017]列队 线段树的更多相关文章
- [NOIP2017]列队(线段树/裂点splay)
考虑n=1的做法,就是支持: 1.在线删一个数 2.在结尾加一个数 3.查询序列的第y个数 用线段树记录区间内被删元素的个数,可以通过线段树上二分快速得解,对于新增的数,用vector记录即可. 对于 ...
- 【noip2017】【Luogu3960】列队 线段树
题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有 n \times mn×m 名学生,方阵的 ...
- Luogu P3960 列队 线段树
题面 线段树入门题. 我们考虑线段树来维护这个矩阵. 首先我们先定n+1棵线段树前n棵维护每行前m-1个同学中没有离队过的同学,还有一棵维护第m列中没有离队过的同学.再定n+1棵线段树前n棵线段树维护 ...
- 洛谷 P3960 [ NOIP 2017 ] 列队 —— 线段树
题目:https://www.luogu.org/problemnew/show/P3960 NOIP 题,不用很复杂的数据结构...但又参考了许多: 要求支持维护删除第 k 个和在末尾插入的数据结构 ...
- [NOIP2017]列队(树状数组)
定义第i行为所有的点(i,j),0<j<m 可以发现,每一行是相对独立的,每一次操作只会影响到当前行和最后一列 考虑每一行和最后一列各开一个树状数组,但这样显然会爆空间 实际上,对于没有离 ...
- NOIP2017 列队 题解报告【56行线段树】
题目描述 Sylvia 是一个热爱学习的女♂孩子. 前段时间,Sylvia 参加了学校的军训.众所周知,军训的时候需要站方阵. Sylvia 所在的方阵中有n \times mn×m名学生,方阵的行数 ...
- NOIP2017提高组Day2T3 列队 洛谷P3960 线段树
原文链接https://www.cnblogs.com/zhouzhendong/p/9265380.html 题目传送门 - 洛谷P3960 题目传送门 - LOJ#2319 题目传送门 - Vij ...
- 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay
正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...
- 2018.11.01 loj#2319. 「NOIP2017」列队(线段树)
传送门 唉突然回忆起去年去noipnoipnoip提高组试水然后省二滚粗的悲惨经历... 往事不堪回首. 所以说考场上真的有debuffdebuffdebuff啊!!!虽然当时我也不会权值线段树 这道 ...
随机推荐
- 关于okHttp框架的使用
在之前的项目中,使用传统的HttpClient来返回一个图片信息流的时候总是报错,最后发现是因为传统的传输方式会对流的大小有限制,当超过某个值的时候就会报异常,最后决定使用OkHttp框架来解决这个问 ...
- JavaSE 第二次学习随笔(关于内存的小题)
class HelloA { public HelloA() { System.out.println("HelloA"); } { System.out.println(&quo ...
- nodeJs 对 Mysql 数据库的 curd
var mysql = require('mysql'); var connection = mysql.createConnection({ host : 'localhost', user : ' ...
- 9.1 IIC驱动源码分析
学习目标:分析linux内核源码下的i2c总线驱动 drivers/i2c/busses/i2c-s3c2410.c 和 driver/i2c/chips/eeprom.c 设备驱动: 一.i2c驱动 ...
- 安装java 和 eclipse
昨天安装eclipse出现个问题, 安装完了创建第一个项目目录的时候弹窗报错an ......什么什么, 百度一堆没有用,后来发现是jdk12不支持,换了jdk8就可以了, 然后eclipse安装py ...
- 洛谷(P1006 传纸条)
题目描述 小渊和小轩是好朋友也是同班同学,他们在一起总有谈不完的话题.一次素质拓展活动中,班上同学安排做成一个mm行nn列的矩阵,而小渊和小轩被安排在矩阵对角线的两端,因此,他们就无法直接交谈了.幸运 ...
- python基础之try异常处理、socket套接字基础part1
异常处理 错误 程序里的错误一般分为两种: 1.语法错误,这种错误,根本过不了python解释器的语法检测,必须在程序执行前就改正 2.逻辑错误,人为造成的错误,如数据类型错误.调用方法错误等,这些解 ...
- 20145202马超《网络对抗》Exp3免杀 进阶
木马化正常软件,如通过改变机器指令.实现可免杀免防火墙提示的后门. 继上次实验3所做的代码在主函数里面加上一行调用就可以 改各种属性,这里我参考了郝浩同学的博客 最后我还是遇到了问题 后来发现虽然有那 ...
- Python的logging模块、os模块、commands模块与sys模块
一.logging模块 import logging logging.debug('This is debug message') logging.info('This is info message ...
- 网页设计简史看设计&代码“隔膜”
本文来自网易云社区 作者:马宝 设计与代码之间隔膜所在?既然你诚心诚意地问了,我就大发慈悲地告诉你.为了防止地球被破坏,为了维护世界的和平,为了贯彻爱与真实的邪恶~,我是穿梭在前端与设计之间爱与美丽的 ...