~~~题面~~~

题解:

  之前写的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. Discuz论坛搜索下拉框插件openSug

    Discuz!只需安装openSug插件即可获得带有“搜索框提示”功能的搜索框,让您的Discuz搜索更便捷! 下载:https://www.opensug.org/faq/.../opensug.d ...

  2. 10.1.5 Comment类型【JavaScript高级程序设计第三版】

    注释在DOM中是通过Comment 类型来表示的.Comment 节点具有下列特征: nodeType 的值为8: nodeName 的值为"#comment": nodeValu ...

  3. FireDAC内存表

    procedure TForm1.FormCreate(Sender: TObject); Var i:integer; begin // i:=; self.FDMemTable1.FieldDef ...

  4. Scrapy进阶

    当我们使用scrapy框架爬取网站的时候,我们会有一个入口的url,一个名为start_urls,我们爬取的第一个网页是从这一开始的. 需求: 现在我们有一个这样的需求,比如说我们对起始的URL有一个 ...

  5. 网站漏洞修复之最新版本UEditor漏洞

    UEditor于近日被曝出高危漏洞,包括目前官方UEditor 1.4.3.3 最新版本,都受到此漏洞的影响,ueditor是百度官方技术团队开发的一套前端编辑器,可以上传图片,写文字,支持自定义的h ...

  6. (数据科学学习手札27)sklearn数据集分割方法汇总

    一.简介 在现实的机器学习任务中,我们往往是利用搜集到的尽可能多的样本集来输入算法进行训练,以尽可能高的精度为目标,但这里便出现一个问题,一是很多情况下我们不能说搜集到的样本集就能代表真实的全体,其分 ...

  7. 最短路径算法 4.SPFA算法(1)

    今天所说的就是常用的解决最短路径问题最后一个算法,这个算法同样是求连通图中单源点到其他结点的最短路径,功能和Bellman-Ford算法大致相同,可以求有负权的边的图,但不能出现负回路.但是SPFA算 ...

  8. linux c fgetc()

    今天练习代码的时候碰见这样一个问题: 一个文件test.txt,文件内容为 1 2 4 5 在程序中读写这个文件,修改其内容,添加一行,将文件内容变成: 1 2 3 4 5 楼主的错误代码是这样的: ...

  9. 【算法】 string 转 int

    [算法] string 转 int 遇到的一道面试题, 当时只写了个思路, 现给出具体实现 ,算是一种比较笨的实现方式 public class StringToInt { /// <summa ...

  10. Autofac小例子

    AutoFac是.net平台下的IOC容器产品.今天学习一下它的使用方法. 1.最简单的使用. public interface ITestDao { string SayHello(); } pub ...