~~~题面~~~

题解:

  之前写的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]列队 线段树的更多相关文章

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

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

  2. 【noip2017】【Luogu3960】列队 线段树

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

  3. Luogu P3960 列队 线段树

    题面 线段树入门题. 我们考虑线段树来维护这个矩阵. 首先我们先定n+1棵线段树前n棵维护每行前m-1个同学中没有离队过的同学,还有一棵维护第m列中没有离队过的同学.再定n+1棵线段树前n棵线段树维护 ...

  4. 洛谷 P3960 [ NOIP 2017 ] 列队 —— 线段树

    题目:https://www.luogu.org/problemnew/show/P3960 NOIP 题,不用很复杂的数据结构...但又参考了许多: 要求支持维护删除第 k 个和在末尾插入的数据结构 ...

  5. [NOIP2017]列队(树状数组)

    定义第i行为所有的点(i,j),0<j<m 可以发现,每一行是相对独立的,每一次操作只会影响到当前行和最后一列 考虑每一行和最后一列各开一个树状数组,但这样显然会爆空间 实际上,对于没有离 ...

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

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

  7. NOIP2017提高组Day2T3 列队 洛谷P3960 线段树

    原文链接https://www.cnblogs.com/zhouzhendong/p/9265380.html 题目传送门 - 洛谷P3960 题目传送门 - LOJ#2319 题目传送门 - Vij ...

  8. 洛谷P3960 列队 NOIp2017 线段树/树状数组/splay

    正解:动态开点线段树 解题报告: 传送门! 因为最近学主席树的时候顺便get到了动态开点线段树?刚好想起来很久很久以前就想做结果一直麻油做的这题,,,所以就做下好了QAQ 然后说下,这题有很多种方法, ...

  9. 2018.11.01 loj#2319. 「NOIP2017」列队(线段树)

    传送门 唉突然回忆起去年去noipnoipnoip提高组试水然后省二滚粗的悲惨经历... 往事不堪回首. 所以说考场上真的有debuffdebuffdebuff啊!!!虽然当时我也不会权值线段树 这道 ...

随机推荐

  1. java 时间转换去杠

    public static String minusHyphen(String dateParam){ if(dateParam ==null) return null; if(dateParam.i ...

  2. vue服务端渲染添加缓存

    缓存 虽然 Vue 的服务器端渲染(SSR)相当快速,但是由于创建组件实例和虚拟 DOM 节点的开销,无法与纯基于字符串拼接(pure string-based)的模板的性能相当.在 SSR 性能至关 ...

  3. phpstudy apache启动失败,80端口占用问题解决方案

    安装phpstydy,启动apache时,启动失败,提示80端口占用,需要将占用80端口的服务进程关闭 1.运行cmd, netstat -ano 找到80端口对应的pid  4 2.一般都是调用 h ...

  4. mysql 5.8 查询最新一条数据

    SELECT * FROM ( ,) FROM (SELECT * FROM or_task_node ORDER BY created_date DESC) temp ) AS vars ) t g ...

  5. STL 入门 (17 暑假集训第一周)

    快速全排列的函数 头文件<algorithm> next_permutation(a,a+n) ---------------------------------------------- ...

  6. 教你如何更改xshell中的转发规则

    使用不同的类型转发,与之对应的端口,所以如果想要使用不同类型的转发就要更改端口使其与之一一对应.本集xshell专栏文章将为大家讲解如何更改转发规则. 更改转发规则操作如下: 1.打开会话对话框. 2 ...

  7. python基础集结号

    Python 号称是最接近人工智能的语言,因为它的动态便捷性和灵活的三方扩展,成就了它在人工智能领域的丰碑 走进Python,靠近人工智能 一.编程语言Python的基础 之 "浅入浅出&q ...

  8. [答网友问]让GridLength支持动画

    原文:[答网友问]让GridLength支持动画 [答网友问]WPF中让GridLength类型支持动画                                                 ...

  9. 从C到C++ (1)

    从C到C++ 一. bool类型 bool取值false和true,是0和1的区别: false可以代表0,但true有很多种,并非只有1. 二. const限定符 常量在定义后就不能修改,所以定义时 ...

  10. 问题:调用 ASP.Net Core WebAPI的HTTP POST方法时,从 [FromBody] 中读取的 MongoDB GeoJsonObjectModel成员总是null

    问题描述: POST/PUT to ASP.Net Core with [FromBody] to a MongoDB GeoJsonObjectModel member is always null ...